Scene.Permissions.cs 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Reflection;
  30. using System.Text;
  31. using log4net;
  32. using OpenMetaverse;
  33. using OpenSim.Framework;
  34. using OpenSim.Region.Framework.Interfaces;
  35. namespace OpenSim.Region.Framework.Scenes
  36. {
  37. #region Delegates
  38. public delegate uint GenerateClientFlagsHandler(SceneObjectPart part, ScenePresence sp, uint curEffectivePerms);
  39. public delegate void SetBypassPermissionsHandler(bool value);
  40. public delegate bool BypassPermissionsHandler();
  41. public delegate bool PropagatePermissionsHandler();
  42. public delegate bool RezObjectHandler(int objectCount, UUID owner, Vector3 objectPosition);
  43. public delegate bool DeleteObjectHandlerByIDs(UUID objectID, UUID deleter);
  44. public delegate bool DeleteObjectHandler(SceneObjectGroup sog, ScenePresence sp);
  45. public delegate bool TransferObjectHandler(UUID objectID, UUID recipient);
  46. public delegate bool TakeObjectHandler(SceneObjectGroup sog, ScenePresence sp);
  47. public delegate bool SellGroupObjectHandler(UUID userID, UUID groupID);
  48. public delegate bool SellObjectHandlerByUserID(SceneObjectGroup sog, UUID userID, byte saleType);
  49. public delegate bool SellObjectHandler(SceneObjectGroup sog, ScenePresence sp, byte saleType);
  50. public delegate bool TakeCopyObjectHandler(SceneObjectGroup sog, ScenePresence sp);
  51. public delegate bool DuplicateObjectHandler(SceneObjectGroup sog, ScenePresence sp);
  52. public delegate bool EditObjectByIDsHandler(UUID objectID, UUID editorID);
  53. public delegate bool EditObjectHandler(SceneObjectGroup sog, ScenePresence sp);
  54. public delegate bool EditObjectPermsHandler(SceneObjectGroup sog, UUID editorID);
  55. public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID);
  56. public delegate bool MoveObjectHandler(SceneObjectGroup sog, ScenePresence sp);
  57. public delegate bool ObjectEntryHandler(SceneObjectGroup sog, bool enteringRegion, Vector3 newPoint);
  58. public delegate bool ObjectEnterWithScriptsHandler(SceneObjectGroup sog, ILandObject land);
  59. public delegate bool ReturnObjectsHandler(ILandObject land, ScenePresence sp, List<SceneObjectGroup> objects);
  60. public delegate bool InstantMessageHandler(UUID user, UUID target);
  61. public delegate bool InventoryTransferHandler(UUID user, UUID target);
  62. public delegate bool ViewScriptHandler(UUID script, UUID objectID, UUID user);
  63. public delegate bool ViewNotecardHandler(UUID script, UUID objectID, UUID user);
  64. public delegate bool EditScriptHandler(UUID script, UUID objectID, UUID user);
  65. public delegate bool EditNotecardHandler(UUID notecard, UUID objectID, UUID user);
  66. public delegate bool RunScriptHandlerByIDs(UUID script, UUID objectID, UUID user);
  67. public delegate bool RunScriptHandler(TaskInventoryItem item, SceneObjectPart part);
  68. public delegate bool CompileScriptHandler(UUID ownerUUID, int scriptType);
  69. public delegate bool StartScriptHandler(UUID script, UUID user);
  70. public delegate bool StopScriptHandler(UUID script, UUID user);
  71. public delegate bool ResetScriptHandler(UUID prim, UUID script, UUID user);
  72. public delegate bool TerraformLandHandler(UUID user, Vector3 position);
  73. public delegate bool RunConsoleCommandHandler(UUID user);
  74. public delegate bool IssueEstateCommandHandler(UUID user, bool ownerCommand);
  75. public delegate bool IsGodHandler(UUID user);
  76. public delegate bool IsGridGodHandler(UUID user);
  77. public delegate bool IsAdministratorHandler(UUID user);
  78. public delegate bool IsEstateManagerHandler(UUID user);
  79. public delegate bool EditParcelHandler(UUID user, ILandObject parcel);
  80. public delegate bool EditParcelPropertiesHandler(UUID user, ILandObject parcel, GroupPowers p, bool allowManager);
  81. public delegate bool SellParcelHandler(UUID user, ILandObject parcel);
  82. public delegate bool AbandonParcelHandler(UUID user, ILandObject parcel);
  83. public delegate bool ReclaimParcelHandler(UUID user, ILandObject parcel);
  84. public delegate bool DeedParcelHandler(UUID user, ILandObject parcel);
  85. public delegate bool DeedObjectHandler(ScenePresence sp, SceneObjectGroup sog, UUID targetGroupID);
  86. public delegate bool BuyLandHandler(UUID user, ILandObject parcel);
  87. public delegate bool LinkObjectHandler(UUID user, UUID objectID);
  88. public delegate bool DelinkObjectHandler(UUID user, UUID objectID);
  89. public delegate bool CreateObjectInventoryHandler(int invType, UUID objectID, UUID userID);
  90. public delegate bool CopyObjectInventoryHandler(UUID itemID, UUID objectID, UUID userID);
  91. public delegate bool DoObjectInvToObjectInv(TaskInventoryItem item, SceneObjectPart sourcePart, SceneObjectPart destPart);
  92. public delegate bool DoDropInObjectInv(InventoryItemBase item, ScenePresence sp, SceneObjectPart destPart);
  93. public delegate bool DeleteObjectInventoryHandler(UUID itemID, UUID objectID, UUID userID);
  94. public delegate bool TransferObjectInventoryHandler(UUID itemID, UUID objectID, UUID userID);
  95. public delegate bool CreateUserInventoryHandler(int invType, UUID userID);
  96. public delegate bool EditUserInventoryHandler(UUID itemID, UUID userID);
  97. public delegate bool CopyUserInventoryHandler(UUID itemID, UUID userID);
  98. public delegate bool DeleteUserInventoryHandler(UUID itemID, UUID userID);
  99. public delegate bool TransferUserInventoryHandler(UUID itemID, UUID userID, UUID recipientID);
  100. public delegate bool TeleportHandler(UUID userID, Scene scene);
  101. public delegate bool ControlPrimMediaHandler(UUID userID, UUID primID, int face);
  102. public delegate bool InteractWithPrimMediaHandler(UUID userID, UUID primID, int face);
  103. #endregion
  104. public class ScenePermissions
  105. {
  106. //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  107. private readonly Scene m_scene;
  108. public ScenePermissions(Scene scene)
  109. {
  110. m_scene = scene;
  111. }
  112. #region events
  113. public event GenerateClientFlagsHandler OnGenerateClientFlags;
  114. public event SetBypassPermissionsHandler OnSetBypassPermissions;
  115. public event BypassPermissionsHandler OnBypassPermissions;
  116. public event PropagatePermissionsHandler OnPropagatePermissions;
  117. public event RezObjectHandler OnRezObject;
  118. public event DeleteObjectHandlerByIDs OnDeleteObjectByIDs;
  119. public event DeleteObjectHandler OnDeleteObject;
  120. public event TransferObjectHandler OnTransferObject;
  121. public event TakeObjectHandler OnTakeObject;
  122. public event SellGroupObjectHandler OnSellGroupObject;
  123. public event SellObjectHandlerByUserID OnSellObjectByUserID;
  124. public event SellObjectHandler OnSellObject;
  125. public event TakeCopyObjectHandler OnTakeCopyObject;
  126. public event DuplicateObjectHandler OnDuplicateObject;
  127. public event EditObjectByIDsHandler OnEditObjectByIDs;
  128. public event EditObjectHandler OnEditObject;
  129. public event EditObjectPermsHandler OnEditObjectPerms;
  130. public event EditObjectInventoryHandler OnEditObjectInventory;
  131. public event MoveObjectHandler OnMoveObject;
  132. public event ObjectEntryHandler OnObjectEntry;
  133. public event ObjectEnterWithScriptsHandler OnObjectEnterWithScripts;
  134. public event ReturnObjectsHandler OnReturnObjects;
  135. public event InstantMessageHandler OnInstantMessage;
  136. public event InventoryTransferHandler OnInventoryTransfer;
  137. public event ViewScriptHandler OnViewScript;
  138. public event ViewNotecardHandler OnViewNotecard;
  139. public event EditScriptHandler OnEditScript;
  140. public event EditNotecardHandler OnEditNotecard;
  141. public event RunScriptHandlerByIDs OnRunScriptByIDs;
  142. public event RunScriptHandler OnRunScript;
  143. public event CompileScriptHandler OnCompileScript;
  144. public event StartScriptHandler OnStartScript;
  145. public event StopScriptHandler OnStopScript;
  146. public event ResetScriptHandler OnResetScript;
  147. public event TerraformLandHandler OnTerraformLand;
  148. public event RunConsoleCommandHandler OnRunConsoleCommand;
  149. public event IssueEstateCommandHandler OnIssueEstateCommand;
  150. public event IsGridGodHandler OnIsGridGod;
  151. public event IsAdministratorHandler OnIsAdministrator;
  152. public event IsEstateManagerHandler OnIsEstateManager;
  153. // public event EditParcelHandler OnEditParcel;
  154. public event EditParcelPropertiesHandler OnEditParcelProperties;
  155. public event SellParcelHandler OnSellParcel;
  156. public event AbandonParcelHandler OnAbandonParcel;
  157. public event ReclaimParcelHandler OnReclaimParcel;
  158. public event DeedParcelHandler OnDeedParcel;
  159. public event DeedObjectHandler OnDeedObject;
  160. public event BuyLandHandler OnBuyLand;
  161. public event LinkObjectHandler OnLinkObject;
  162. public event DelinkObjectHandler OnDelinkObject;
  163. public event CreateObjectInventoryHandler OnCreateObjectInventory;
  164. public event CopyObjectInventoryHandler OnCopyObjectInventory;
  165. public event DoObjectInvToObjectInv OnDoObjectInvToObjectInv;
  166. public event DoDropInObjectInv OnDropInObjectInv;
  167. public event DeleteObjectInventoryHandler OnDeleteObjectInventory;
  168. public event TransferObjectInventoryHandler OnTransferObjectInventory;
  169. public event CreateUserInventoryHandler OnCreateUserInventory;
  170. public event EditUserInventoryHandler OnEditUserInventory;
  171. public event CopyUserInventoryHandler OnCopyUserInventory;
  172. public event DeleteUserInventoryHandler OnDeleteUserInventory;
  173. public event TransferUserInventoryHandler OnTransferUserInventory;
  174. public event TeleportHandler OnTeleport;
  175. public event ControlPrimMediaHandler OnControlPrimMedia;
  176. public event InteractWithPrimMediaHandler OnInteractWithPrimMedia;
  177. #endregion
  178. #region Object Permission Checks
  179. public uint GenerateClientFlags( SceneObjectPart part, ScenePresence sp)
  180. {
  181. const PrimFlags DEFAULT_FLAGS =
  182. PrimFlags.ObjectModify |
  183. PrimFlags.ObjectCopy |
  184. PrimFlags.ObjectMove |
  185. PrimFlags.ObjectTransfer |
  186. PrimFlags.ObjectYouOwner |
  187. PrimFlags.ObjectAnyOwner |
  188. PrimFlags.ObjectOwnerModify;
  189. if (part is null)
  190. return 0;
  191. uint perms = part.GetEffectiveObjectFlags() | (uint)DEFAULT_FLAGS;
  192. GenerateClientFlagsHandler handlerGenerateClientFlags = OnGenerateClientFlags;
  193. if (handlerGenerateClientFlags is not null)
  194. {
  195. foreach (GenerateClientFlagsHandler check in handlerGenerateClientFlags.GetInvocationList().AsSpan())
  196. {
  197. perms &= check(part, sp, perms);
  198. }
  199. }
  200. return perms;
  201. }
  202. public void SetBypassPermissions(bool value)
  203. {
  204. OnSetBypassPermissions?.Invoke(value);
  205. }
  206. public bool BypassPermissions()
  207. {
  208. BypassPermissionsHandler handler = OnBypassPermissions;
  209. if (handler is not null)
  210. {
  211. foreach (BypassPermissionsHandler h in handler.GetInvocationList().AsSpan())
  212. {
  213. if (h() == false)
  214. return false;
  215. }
  216. }
  217. return true;
  218. }
  219. public bool PropagatePermissions()
  220. {
  221. PropagatePermissionsHandler handler = OnPropagatePermissions;
  222. if (handler is not null)
  223. {
  224. foreach (PropagatePermissionsHandler h in handler.GetInvocationList().AsSpan())
  225. {
  226. if (h() == false)
  227. return false;
  228. }
  229. }
  230. return true;
  231. }
  232. #region REZ OBJECT
  233. public bool CanRezObject(int objectCount, UUID owner, Vector3 objectPosition)
  234. {
  235. RezObjectHandler handler = OnRezObject;
  236. if (handler is not null)
  237. {
  238. foreach (RezObjectHandler h in handler.GetInvocationList().AsSpan())
  239. {
  240. if (h(objectCount, owner,objectPosition) == false)
  241. return false;
  242. }
  243. }
  244. return true;
  245. }
  246. #endregion
  247. #region DELETE OBJECT
  248. public bool CanDeleteObject(UUID objectID, UUID deleter)
  249. {
  250. bool result = true;
  251. DeleteObjectHandlerByIDs handler = OnDeleteObjectByIDs;
  252. if (handler is not null)
  253. {
  254. foreach (DeleteObjectHandlerByIDs h in handler.GetInvocationList().AsSpan())
  255. {
  256. if (h(objectID, deleter) == false)
  257. {
  258. result = false;
  259. break;
  260. }
  261. }
  262. }
  263. return result;
  264. }
  265. public bool CanDeleteObject(SceneObjectGroup sog, IClientAPI client)
  266. {
  267. DeleteObjectHandler handler = OnDeleteObject;
  268. if (handler is not null)
  269. {
  270. if(sog is null || client is null || client.SceneAgent is null)
  271. return false;
  272. ScenePresence sp = client.SceneAgent as ScenePresence;
  273. foreach (DeleteObjectHandler h in handler.GetInvocationList().AsSpan())
  274. {
  275. if (h(sog, sp) == false)
  276. return false;
  277. }
  278. }
  279. return true;
  280. }
  281. public bool CanTransferObject(UUID objectID, UUID recipient)
  282. {
  283. TransferObjectHandler handler = OnTransferObject;
  284. if (handler is not null)
  285. {
  286. foreach (TransferObjectHandler h in handler.GetInvocationList().AsSpan())
  287. {
  288. if (h(objectID, recipient) == false)
  289. return false;
  290. }
  291. }
  292. return true;
  293. }
  294. #endregion
  295. #region TAKE OBJECT
  296. public bool CanTakeObject(SceneObjectGroup sog, ScenePresence sp)
  297. {
  298. TakeObjectHandler handler = OnTakeObject;
  299. if (handler is not null)
  300. {
  301. if(sog is null || sp is null)
  302. return false;
  303. foreach (TakeObjectHandler h in handler.GetInvocationList().AsSpan())
  304. {
  305. if (h(sog, sp) == false)
  306. return false;
  307. }
  308. }
  309. //m_log.DebugFormat(
  310. // "[SCENE PERMISSIONS]: CanTakeObject() fired for object {0}, taker {1}, result {2}",
  311. // objectID, AvatarTakingUUID, result);
  312. return true;
  313. }
  314. #endregion
  315. #region SELL GROUP OBJECT
  316. public bool CanSellGroupObject(UUID userID, UUID groupID)
  317. {
  318. SellGroupObjectHandler handler = OnSellGroupObject;
  319. if (handler is not null)
  320. {
  321. foreach (SellGroupObjectHandler h in handler.GetInvocationList().AsSpan())
  322. {
  323. if (h(userID, groupID) == false)
  324. return false;
  325. }
  326. }
  327. //m_log.DebugFormat(
  328. // "[SCENE PERMISSIONS]: CanSellGroupObject() fired for user {0}, group {1}, result {2}",
  329. // userID, groupID, result);
  330. return true;
  331. }
  332. #endregion
  333. #region SELL OBJECT
  334. public bool CanSellObject(IClientAPI client, SceneObjectGroup sog, byte saleType)
  335. {
  336. SellObjectHandler handler = OnSellObject;
  337. if (handler is not null)
  338. {
  339. if(sog is null || client is null || client.SceneAgent is null)
  340. return false;
  341. ScenePresence sp = client.SceneAgent as ScenePresence;
  342. foreach (SellObjectHandler h in handler.GetInvocationList().AsSpan())
  343. {
  344. if (h(sog, sp, saleType) == false)
  345. return false;
  346. }
  347. }
  348. return true;
  349. }
  350. public bool CanSellObject(UUID userID, SceneObjectGroup sog, byte saleType)
  351. {
  352. SellObjectHandlerByUserID handler = OnSellObjectByUserID;
  353. if (handler is not null)
  354. {
  355. if(sog is null)
  356. return false;
  357. foreach (SellObjectHandlerByUserID h in handler.GetInvocationList().AsSpan())
  358. {
  359. if (h(sog, userID, saleType) == false)
  360. return false;
  361. }
  362. }
  363. return true;
  364. }
  365. #endregion
  366. #region TAKE COPY OBJECT
  367. public bool CanTakeCopyObject(SceneObjectGroup sog, ScenePresence sp)
  368. {
  369. TakeCopyObjectHandler handler = OnTakeCopyObject;
  370. if (handler is not null)
  371. {
  372. if(sog is null || sp is null)
  373. return false;
  374. foreach (TakeCopyObjectHandler h in handler.GetInvocationList().AsSpan())
  375. {
  376. if (h(sog, sp) == false)
  377. return false;
  378. }
  379. }
  380. //m_log.DebugFormat(
  381. // "[SCENE PERMISSIONS]: CanTakeCopyObject() fired for object {0}, user {1}, result {2}",
  382. // objectID, userID, result);
  383. return true;
  384. }
  385. #endregion
  386. #region DUPLICATE OBJECT
  387. public bool CanDuplicateObject(SceneObjectGroup sog, UUID agentID)
  388. {
  389. DuplicateObjectHandler handler = OnDuplicateObject;
  390. if (handler is not null)
  391. {
  392. if(sog is null || sog.IsDeleted)
  393. return false;
  394. ScenePresence sp = m_scene.GetScenePresence(agentID);
  395. if(sp is null || sp.IsDeleted)
  396. return false;
  397. foreach (DuplicateObjectHandler h in handler.GetInvocationList().AsSpan())
  398. {
  399. if (h(sog, sp) == false)
  400. return false;
  401. }
  402. }
  403. return true;
  404. }
  405. #endregion
  406. #region persence EDIT or MOVE OBJECT
  407. private const uint CANSELECTMASK = (uint)(
  408. PrimFlags.ObjectMove |
  409. PrimFlags.ObjectModify |
  410. PrimFlags.ObjectOwnerModify
  411. );
  412. public bool CanChangeSelectedState(SceneObjectPart part, ScenePresence sp)
  413. {
  414. uint perms = GenerateClientFlags(part, sp);
  415. return (perms & CANSELECTMASK) != 0;
  416. }
  417. #endregion
  418. #region EDIT OBJECT
  419. public bool CanEditObject(UUID objectID, UUID editorID)
  420. {
  421. EditObjectByIDsHandler handler = OnEditObjectByIDs;
  422. if (handler is not null)
  423. {
  424. foreach (EditObjectByIDsHandler h in handler.GetInvocationList().AsSpan())
  425. {
  426. if (h(objectID, editorID) == false)
  427. return false;
  428. }
  429. }
  430. return true;
  431. }
  432. public bool CanEditObject(SceneObjectGroup sog, IClientAPI client)
  433. {
  434. EditObjectHandler handler = OnEditObject;
  435. if (handler is not null)
  436. {
  437. if(sog is null || client is null || client.SceneAgent is null)
  438. return false;
  439. ScenePresence sp = client.SceneAgent as ScenePresence;
  440. foreach (EditObjectHandler h in handler.GetInvocationList().AsSpan())
  441. {
  442. if (h(sog, sp) == false)
  443. return false;
  444. }
  445. }
  446. return true;
  447. }
  448. public bool CanEditObjectPermissions(SceneObjectGroup sog, UUID editorID)
  449. {
  450. EditObjectPermsHandler handler = OnEditObjectPerms;
  451. if (handler is not null)
  452. {
  453. if(sog is null)
  454. return false;
  455. foreach (EditObjectPermsHandler h in handler.GetInvocationList().AsSpan())
  456. {
  457. if (h(sog, editorID) == false)
  458. return false;
  459. }
  460. }
  461. return true;
  462. }
  463. public bool CanEditObjectInventory(UUID objectID, UUID editorID)
  464. {
  465. EditObjectInventoryHandler handler = OnEditObjectInventory;
  466. if (handler is not null)
  467. {
  468. foreach (EditObjectInventoryHandler h in handler.GetInvocationList().AsSpan())
  469. {
  470. if (h(objectID, editorID) == false)
  471. return false;
  472. }
  473. }
  474. return true;
  475. }
  476. #endregion
  477. #region MOVE OBJECT
  478. public bool CanMoveObject(SceneObjectGroup sog, IClientAPI client)
  479. {
  480. MoveObjectHandler handler = OnMoveObject;
  481. if (handler is not null)
  482. {
  483. if(sog is null || client is null || client.SceneAgent is null)
  484. return false;
  485. ScenePresence sp = client.SceneAgent as ScenePresence;
  486. foreach (MoveObjectHandler h in handler.GetInvocationList().AsSpan())
  487. {
  488. if (h(sog, sp) == false)
  489. return false;
  490. }
  491. }
  492. return true;
  493. }
  494. #endregion
  495. #region OBJECT ENTRY
  496. public bool CanObjectEntry(SceneObjectGroup sog, bool enteringRegion, Vector3 newPoint)
  497. {
  498. ObjectEntryHandler handler = OnObjectEntry;
  499. if (handler is not null)
  500. {
  501. foreach (ObjectEntryHandler h in handler.GetInvocationList().AsSpan())
  502. {
  503. if (h(sog, enteringRegion, newPoint) == false)
  504. return false;
  505. }
  506. }
  507. return true;
  508. }
  509. public bool CanObjectEnterWithScripts(SceneObjectGroup sog, ILandObject land)
  510. {
  511. ObjectEnterWithScriptsHandler handler = OnObjectEnterWithScripts;
  512. if (handler is not null)
  513. {
  514. foreach (ObjectEnterWithScriptsHandler h in handler.GetInvocationList().AsSpan())
  515. {
  516. if (h(sog, land) == false)
  517. return false;
  518. }
  519. }
  520. return true;
  521. }
  522. #endregion
  523. #region RETURN OBJECT
  524. public bool CanReturnObjects(ILandObject land, IClientAPI client, List<SceneObjectGroup> objects)
  525. {
  526. ReturnObjectsHandler handler = OnReturnObjects;
  527. if (handler is not null)
  528. {
  529. if(objects is null)
  530. return false;
  531. ScenePresence sp = null;
  532. if(client is not null && client.SceneAgent is not null)
  533. sp = client.SceneAgent as ScenePresence;
  534. foreach (ReturnObjectsHandler h in handler.GetInvocationList().AsSpan())
  535. {
  536. if (h(land, sp, objects) == false)
  537. return false;
  538. }
  539. }
  540. //m_log.DebugFormat(
  541. // "[SCENE PERMISSIONS]: CanReturnObjects() fired for user {0} for {1} objects on {2}, result {3}",
  542. // user, objects.Count, land.LandData.Name, result);
  543. return true;
  544. }
  545. #endregion
  546. #region INSTANT MESSAGE
  547. public bool CanInstantMessage(UUID user, UUID target)
  548. {
  549. InstantMessageHandler handler = OnInstantMessage;
  550. if (handler is not null)
  551. {
  552. foreach (InstantMessageHandler h in handler.GetInvocationList().AsSpan())
  553. {
  554. if (h(user, target) == false)
  555. return false;
  556. }
  557. }
  558. return true;
  559. }
  560. #endregion
  561. #region INVENTORY TRANSFER
  562. public bool CanInventoryTransfer(UUID user, UUID target)
  563. {
  564. InventoryTransferHandler handler = OnInventoryTransfer;
  565. if (handler is not null)
  566. {
  567. foreach (InventoryTransferHandler h in handler.GetInvocationList().AsSpan())
  568. {
  569. if (h(user, target) == false)
  570. return false;
  571. }
  572. }
  573. return true;
  574. }
  575. #endregion
  576. #region VIEW SCRIPT
  577. public bool CanViewScript(UUID script, UUID objectID, UUID user)
  578. {
  579. ViewScriptHandler handler = OnViewScript;
  580. if (handler is not null)
  581. {
  582. foreach (ViewScriptHandler h in handler.GetInvocationList().AsSpan())
  583. {
  584. if (h(script, objectID, user) == false)
  585. return false;
  586. }
  587. }
  588. return true;
  589. }
  590. public bool CanViewNotecard(UUID script, UUID objectID, UUID user)
  591. {
  592. ViewNotecardHandler handler = OnViewNotecard;
  593. if (handler is not null)
  594. {
  595. foreach (ViewNotecardHandler h in handler.GetInvocationList().AsSpan())
  596. {
  597. if (h(script, objectID, user) == false)
  598. return false;
  599. }
  600. }
  601. return true;
  602. }
  603. #endregion
  604. #region EDIT SCRIPT
  605. public bool CanEditScript(UUID script, UUID objectID, UUID user)
  606. {
  607. EditScriptHandler handler = OnEditScript;
  608. if (handler is not null)
  609. {
  610. foreach (EditScriptHandler h in handler.GetInvocationList().AsSpan())
  611. {
  612. if (h(script, objectID, user) == false)
  613. return false;
  614. }
  615. }
  616. return true;
  617. }
  618. public bool CanEditNotecard(UUID script, UUID objectID, UUID user)
  619. {
  620. EditNotecardHandler handler = OnEditNotecard;
  621. if (handler is not null)
  622. {
  623. foreach (EditNotecardHandler h in handler.GetInvocationList().AsSpan())
  624. {
  625. if (h(script, objectID, user) == false)
  626. return false;
  627. }
  628. }
  629. return true;
  630. }
  631. #endregion
  632. #region RUN SCRIPT (When Script Placed in Object)
  633. public bool CanRunScript(UUID script, UUID objectID, UUID user)
  634. {
  635. RunScriptHandlerByIDs handler = OnRunScriptByIDs;
  636. if (handler is not null)
  637. {
  638. foreach (RunScriptHandlerByIDs h in handler.GetInvocationList().AsSpan())
  639. {
  640. if (h(script, objectID, user) == false)
  641. return false;
  642. }
  643. }
  644. return true;
  645. }
  646. public bool CanRunScript(TaskInventoryItem item, SceneObjectPart part)
  647. {
  648. RunScriptHandler handler = OnRunScript;
  649. if (handler is not null)
  650. {
  651. if(item is null || part is null)
  652. return false;
  653. foreach (RunScriptHandler h in handler.GetInvocationList().AsSpan())
  654. {
  655. if (h(item, part) == false)
  656. return false;
  657. }
  658. }
  659. return true;
  660. }
  661. #endregion
  662. #region COMPILE SCRIPT (When Script needs to get (re)compiled)
  663. public bool CanCompileScript(UUID ownerUUID, int scriptType)
  664. {
  665. CompileScriptHandler handler = OnCompileScript;
  666. if (handler is not null)
  667. {
  668. foreach (CompileScriptHandler h in handler.GetInvocationList().AsSpan())
  669. {
  670. if (h(ownerUUID, scriptType) == false)
  671. return false;
  672. }
  673. }
  674. return true;
  675. }
  676. #endregion
  677. #region START SCRIPT (When Script run box is Checked after placed in object)
  678. public bool CanStartScript(UUID script, UUID user)
  679. {
  680. StartScriptHandler handler = OnStartScript;
  681. if (handler is not null)
  682. {
  683. foreach (StartScriptHandler h in handler.GetInvocationList().AsSpan())
  684. {
  685. if (h(script, user) == false)
  686. return false;
  687. }
  688. }
  689. return true;
  690. }
  691. #endregion
  692. #region STOP SCRIPT (When Script run box is unchecked after placed in object)
  693. public bool CanStopScript(UUID script, UUID user)
  694. {
  695. StopScriptHandler handler = OnStopScript;
  696. if (handler is not null)
  697. {
  698. foreach (StopScriptHandler h in handler.GetInvocationList().AsSpan())
  699. {
  700. if (h(script, user) == false)
  701. return false;
  702. }
  703. }
  704. return true;
  705. }
  706. #endregion
  707. #region RESET SCRIPT
  708. public bool CanResetScript(UUID prim, UUID script, UUID user)
  709. {
  710. ResetScriptHandler handler = OnResetScript;
  711. if (handler is not null)
  712. {
  713. foreach (ResetScriptHandler h in handler.GetInvocationList().AsSpan())
  714. {
  715. if (h(prim, script, user) == false)
  716. return false;
  717. }
  718. }
  719. return true;
  720. }
  721. #endregion
  722. #region TERRAFORM LAND
  723. // if pos.x < 0, pos.y <0 and pos.z >=0 pos.z is parcel localID
  724. // id pos.z < 0 x a and y identify the parcel
  725. public bool CanTerraformLand(UUID user, Vector3 pos)
  726. {
  727. TerraformLandHandler handler = OnTerraformLand;
  728. if (handler is not null)
  729. {
  730. foreach (TerraformLandHandler h in handler.GetInvocationList().AsSpan())
  731. {
  732. if (h(user, pos) == false)
  733. return false;
  734. }
  735. }
  736. return true;
  737. }
  738. #endregion
  739. #region RUN CONSOLE COMMAND
  740. public bool CanRunConsoleCommand(UUID user)
  741. {
  742. RunConsoleCommandHandler handler = OnRunConsoleCommand;
  743. if (handler is not null)
  744. {
  745. foreach (RunConsoleCommandHandler h in handler.GetInvocationList().AsSpan())
  746. {
  747. if (h(user) == false)
  748. return false;
  749. }
  750. }
  751. return true;
  752. }
  753. #endregion
  754. #region CAN ISSUE ESTATE COMMAND
  755. public bool CanIssueEstateCommand(UUID user, bool ownerCommand)
  756. {
  757. IssueEstateCommandHandler handler = OnIssueEstateCommand;
  758. if (handler is not null)
  759. {
  760. foreach (IssueEstateCommandHandler h in handler.GetInvocationList().AsSpan())
  761. {
  762. if (h(user, ownerCommand) == false)
  763. return false;
  764. }
  765. }
  766. return true;
  767. }
  768. #endregion
  769. #region CAN BE GODLIKE
  770. public bool IsGod(UUID user)
  771. {
  772. IsAdministratorHandler handler = OnIsAdministrator;
  773. if (handler is not null)
  774. {
  775. foreach (IsAdministratorHandler h in handler.GetInvocationList().AsSpan())
  776. {
  777. if (h(user) == false)
  778. return false;
  779. }
  780. }
  781. return true;
  782. }
  783. public bool IsGridGod(UUID user)
  784. {
  785. IsGridGodHandler handler = OnIsGridGod;
  786. if (handler is not null)
  787. {
  788. foreach (IsGridGodHandler h in handler.GetInvocationList().AsSpan())
  789. {
  790. if (h(user) == false)
  791. return false;
  792. }
  793. }
  794. return true;
  795. }
  796. public bool IsAdministrator(UUID user)
  797. {
  798. IsAdministratorHandler handler = OnIsAdministrator;
  799. if (handler is not null)
  800. {
  801. foreach (IsAdministratorHandler h in handler.GetInvocationList().AsSpan())
  802. {
  803. if (h(user) == false)
  804. return false;
  805. }
  806. }
  807. return true;
  808. }
  809. #endregion
  810. public bool IsEstateManager(UUID user)
  811. {
  812. IsEstateManagerHandler handler = OnIsEstateManager;
  813. if (handler is not null)
  814. {
  815. foreach (IsEstateManagerHandler h in handler.GetInvocationList().AsSpan())
  816. {
  817. if (h(user) == false)
  818. return false;
  819. }
  820. }
  821. return true;
  822. }
  823. #region EDIT PARCEL
  824. public bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p, bool allowManager)
  825. {
  826. EditParcelPropertiesHandler handler = OnEditParcelProperties;
  827. if (handler is not null)
  828. {
  829. foreach (EditParcelPropertiesHandler h in handler.GetInvocationList().AsSpan())
  830. {
  831. if (h(user, parcel, p, allowManager) == false)
  832. return false;
  833. }
  834. }
  835. return true;
  836. }
  837. #endregion
  838. #region SELL PARCEL
  839. public bool CanSellParcel(UUID user, ILandObject parcel)
  840. {
  841. SellParcelHandler handler = OnSellParcel;
  842. if (handler is not null)
  843. {
  844. foreach (SellParcelHandler h in handler.GetInvocationList().AsSpan())
  845. {
  846. if (h(user, parcel) == false)
  847. return false;
  848. }
  849. }
  850. return true;
  851. }
  852. #endregion
  853. #region ABANDON PARCEL
  854. public bool CanAbandonParcel(UUID user, ILandObject parcel)
  855. {
  856. AbandonParcelHandler handler = OnAbandonParcel;
  857. if (handler is not null)
  858. {
  859. foreach (AbandonParcelHandler h in handler.GetInvocationList().AsSpan())
  860. {
  861. if (h(user, parcel) == false)
  862. return false;
  863. }
  864. }
  865. return true;
  866. }
  867. #endregion
  868. public bool CanReclaimParcel(UUID user, ILandObject parcel)
  869. {
  870. ReclaimParcelHandler handler = OnReclaimParcel;
  871. if (handler is not null)
  872. {
  873. foreach (ReclaimParcelHandler h in handler.GetInvocationList().AsSpan())
  874. {
  875. if (h(user, parcel) == false)
  876. return false;
  877. }
  878. }
  879. return true;
  880. }
  881. public bool CanDeedParcel(UUID user, ILandObject parcel)
  882. {
  883. DeedParcelHandler handler = OnDeedParcel;
  884. if (handler is not null)
  885. {
  886. foreach (DeedParcelHandler h in handler.GetInvocationList().AsSpan())
  887. {
  888. if (h(user, parcel) == false)
  889. return false;
  890. }
  891. }
  892. return true;
  893. }
  894. public bool CanDeedObject(IClientAPI client, SceneObjectGroup sog, UUID targetGroupID)
  895. {
  896. DeedObjectHandler handler = OnDeedObject;
  897. if (handler is not null)
  898. {
  899. if(sog is null || client is null || client.SceneAgent is null || targetGroupID.IsZero())
  900. return false;
  901. ScenePresence sp = client.SceneAgent as ScenePresence;
  902. foreach (DeedObjectHandler h in handler.GetInvocationList().AsSpan())
  903. {
  904. if (h(sp, sog, targetGroupID) == false)
  905. return false;
  906. }
  907. }
  908. return true;
  909. }
  910. public bool CanBuyLand(UUID user, ILandObject parcel)
  911. {
  912. BuyLandHandler handler = OnBuyLand;
  913. if (handler is not null)
  914. {
  915. foreach (BuyLandHandler h in handler.GetInvocationList().AsSpan())
  916. {
  917. if (h(user, parcel) == false)
  918. return false;
  919. }
  920. }
  921. return true;
  922. }
  923. public bool CanLinkObject(UUID user, UUID objectID)
  924. {
  925. LinkObjectHandler handler = OnLinkObject;
  926. if (handler is not null)
  927. {
  928. foreach (LinkObjectHandler h in handler.GetInvocationList().AsSpan())
  929. {
  930. if (h(user, objectID) == false)
  931. return false;
  932. }
  933. }
  934. return true;
  935. }
  936. public bool CanDelinkObject(UUID user, UUID objectID)
  937. {
  938. DelinkObjectHandler handler = OnDelinkObject;
  939. if (handler is not null)
  940. {
  941. foreach (DelinkObjectHandler h in handler.GetInvocationList().AsSpan())
  942. {
  943. if (h(user, objectID) == false)
  944. return false;
  945. }
  946. }
  947. return true;
  948. }
  949. #endregion
  950. /// Check whether the specified user is allowed to directly create the given inventory type in a prim's
  951. /// inventory (e.g. the New Script button in the 1.21 Linden Lab client).
  952. /// </summary>
  953. /// <param name="invType"></param>
  954. /// <param name="objectID"></param>
  955. /// <param name="userID"></param>
  956. /// <returns></returns>
  957. public bool CanCreateObjectInventory(int invType, UUID objectID, UUID userID)
  958. {
  959. CreateObjectInventoryHandler handler = OnCreateObjectInventory;
  960. if (handler is not null)
  961. {
  962. foreach (CreateObjectInventoryHandler h in handler.GetInvocationList().AsSpan())
  963. {
  964. if (h(invType, objectID, userID) == false)
  965. return false;
  966. }
  967. }
  968. return true;
  969. }
  970. public bool CanCopyObjectInventory(UUID itemID, UUID objectID, UUID userID)
  971. {
  972. CopyObjectInventoryHandler handler = OnCopyObjectInventory;
  973. if (handler is not null)
  974. {
  975. foreach (CopyObjectInventoryHandler h in handler.GetInvocationList().AsSpan())
  976. {
  977. if (h(itemID, objectID, userID) == false)
  978. return false;
  979. }
  980. }
  981. return true;
  982. }
  983. public bool CanDoObjectInvToObjectInv(TaskInventoryItem item, SceneObjectPart sourcePart, SceneObjectPart destPart)
  984. {
  985. DoObjectInvToObjectInv handler = OnDoObjectInvToObjectInv;
  986. if (handler is not null)
  987. {
  988. if (sourcePart is null || destPart is null || item is null)
  989. return false;
  990. foreach (DoObjectInvToObjectInv h in handler.GetInvocationList().AsSpan())
  991. {
  992. if (h(item, sourcePart, destPart) == false)
  993. return false;
  994. }
  995. }
  996. return true;
  997. }
  998. public bool CanDropInObjectInv(InventoryItemBase item, IClientAPI client, SceneObjectPart destPart)
  999. {
  1000. DoDropInObjectInv handler = OnDropInObjectInv;
  1001. if (handler is not null)
  1002. {
  1003. if (client is null || destPart is null || item is null)
  1004. return false;
  1005. if(client.SceneAgent is not ScenePresence sp || sp.IsDeleted)
  1006. return false;
  1007. Delegate[] list = handler.GetInvocationList();
  1008. foreach (DoDropInObjectInv h in list)
  1009. {
  1010. if (h(item, sp, destPart) == false)
  1011. return false;
  1012. }
  1013. }
  1014. return true;
  1015. }
  1016. public bool CanDeleteObjectInventory(UUID itemID, UUID objectID, UUID userID)
  1017. {
  1018. DeleteObjectInventoryHandler handler = OnDeleteObjectInventory;
  1019. if (handler is not null)
  1020. {
  1021. foreach (DeleteObjectInventoryHandler h in handler.GetInvocationList().AsSpan())
  1022. {
  1023. if (h(itemID, objectID, userID) == false)
  1024. return false;
  1025. }
  1026. }
  1027. return true;
  1028. }
  1029. public bool CanTransferObjectInventory(UUID itemID, UUID objectID, UUID userID)
  1030. {
  1031. TransferObjectInventoryHandler handler = OnTransferObjectInventory;
  1032. if (handler is not null)
  1033. {
  1034. foreach (TransferObjectInventoryHandler h in handler.GetInvocationList().AsSpan())
  1035. {
  1036. if (h(itemID, objectID, userID) == false)
  1037. return false;
  1038. }
  1039. }
  1040. return true;
  1041. }
  1042. /// <summary>
  1043. /// Check whether the specified user is allowed to create the given inventory type in their inventory.
  1044. /// </summary>
  1045. /// <param name="invType"></param>
  1046. /// <param name="userID"></param>
  1047. /// <returns></returns>
  1048. public bool CanCreateUserInventory(int invType, UUID userID)
  1049. {
  1050. CreateUserInventoryHandler handler = OnCreateUserInventory;
  1051. if (handler is not null)
  1052. {
  1053. foreach (CreateUserInventoryHandler h in handler.GetInvocationList().AsSpan())
  1054. {
  1055. if (h(invType, userID) == false)
  1056. return false;
  1057. }
  1058. }
  1059. return true;
  1060. }
  1061. /// <summary>
  1062. /// Check whether the specified user is allowed to edit the given inventory item within their own inventory.
  1063. /// </summary>
  1064. /// <param name="itemID"></param>
  1065. /// <param name="userID"></param>
  1066. /// <returns></returns>
  1067. public bool CanEditUserInventory(UUID itemID, UUID userID)
  1068. {
  1069. EditUserInventoryHandler handler = OnEditUserInventory;
  1070. if (handler is not null)
  1071. {
  1072. foreach (EditUserInventoryHandler h in handler.GetInvocationList().AsSpan())
  1073. {
  1074. if (h(itemID, userID) == false)
  1075. return false;
  1076. }
  1077. }
  1078. return true;
  1079. }
  1080. /// <summary>
  1081. /// Check whether the specified user is allowed to copy the given inventory item from their own inventory.
  1082. /// </summary>
  1083. /// <param name="itemID"></param>
  1084. /// <param name="userID"></param>
  1085. /// <returns></returns>
  1086. public bool CanCopyUserInventory(UUID itemID, UUID userID)
  1087. {
  1088. CopyUserInventoryHandler handler = OnCopyUserInventory;
  1089. if (handler is not null)
  1090. {
  1091. foreach (CopyUserInventoryHandler h in handler.GetInvocationList().AsSpan())
  1092. {
  1093. if (h(itemID, userID) == false)
  1094. return false;
  1095. }
  1096. }
  1097. return true;
  1098. }
  1099. /// <summary>
  1100. /// Check whether the specified user is allowed to edit the given inventory item within their own inventory.
  1101. /// </summary>
  1102. /// <param name="itemID"></param>
  1103. /// <param name="userID"></param>
  1104. /// <returns></returns>
  1105. public bool CanDeleteUserInventory(UUID itemID, UUID userID)
  1106. {
  1107. DeleteUserInventoryHandler handler = OnDeleteUserInventory;
  1108. if (handler is not null)
  1109. {
  1110. foreach (DeleteUserInventoryHandler h in handler.GetInvocationList().AsSpan())
  1111. {
  1112. if (h(itemID, userID) == false)
  1113. return false;
  1114. }
  1115. }
  1116. return true;
  1117. }
  1118. public bool CanTransferUserInventory(UUID itemID, UUID userID, UUID recipientID)
  1119. {
  1120. TransferUserInventoryHandler handler = OnTransferUserInventory;
  1121. if (handler is not null)
  1122. {
  1123. foreach (TransferUserInventoryHandler h in handler.GetInvocationList().AsSpan())
  1124. {
  1125. if (h(itemID, userID, recipientID) == false)
  1126. return false;
  1127. }
  1128. }
  1129. return true;
  1130. }
  1131. public bool CanTeleport(UUID userID)
  1132. {
  1133. TeleportHandler handler = OnTeleport;
  1134. if (handler is not null)
  1135. {
  1136. foreach (TeleportHandler h in handler.GetInvocationList().AsSpan())
  1137. {
  1138. if (h(userID, m_scene) == false)
  1139. return false;
  1140. }
  1141. }
  1142. return true;
  1143. }
  1144. public bool CanControlPrimMedia(UUID userID, UUID primID, int face)
  1145. {
  1146. ControlPrimMediaHandler handler = OnControlPrimMedia;
  1147. if (handler is not null)
  1148. {
  1149. foreach (ControlPrimMediaHandler h in handler.GetInvocationList().AsSpan())
  1150. {
  1151. if (h(userID, primID, face) == false)
  1152. return false;
  1153. }
  1154. }
  1155. return true;
  1156. }
  1157. public bool CanInteractWithPrimMedia(UUID userID, UUID primID, int face)
  1158. {
  1159. InteractWithPrimMediaHandler handler = OnInteractWithPrimMedia;
  1160. if (handler is not null)
  1161. {
  1162. foreach (InteractWithPrimMediaHandler h in handler.GetInvocationList().AsSpan())
  1163. {
  1164. if (h(userID, primID, face) == false)
  1165. return false;
  1166. }
  1167. }
  1168. return true;
  1169. }
  1170. }
  1171. }