1
0

SceneObjectPartInventory.cs 72 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926
  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.Text;
  29. using System.Xml;
  30. using System.Collections.Generic;
  31. using System.Collections;
  32. using System.Reflection;
  33. using OpenMetaverse;
  34. using log4net;
  35. using OpenSim.Framework;
  36. using OpenSim.Region.Framework.Interfaces;
  37. using PermissionMask = OpenSim.Framework.PermissionMask;
  38. namespace OpenSim.Region.Framework.Scenes
  39. {
  40. public class SceneObjectPartInventory : IEntityInventory , IDisposable
  41. {
  42. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  43. private byte[] m_inventoryFileData = Array.Empty<byte>();
  44. private byte[] m_inventoryFileNameBytes = Array.Empty<byte>();
  45. private string m_inventoryFileName = "";
  46. private uint m_inventoryFileNameSerial = 0;
  47. private int m_inventoryPrivileged = 0;
  48. private object m_inventoryFileLock = new object();
  49. private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
  50. /// <value>
  51. /// The part to which the inventory belongs.
  52. /// </value>
  53. private SceneObjectPart m_part;
  54. /// <summary>
  55. /// Serial count for inventory file , used to tell if inventory has changed
  56. /// no need for this to be part of Database backup
  57. /// </summary>
  58. protected uint m_inventorySerial = 0;
  59. /// <summary>
  60. /// Holds in memory prim inventory
  61. /// </summary>
  62. protected TaskInventoryDictionary m_items = new TaskInventoryDictionary();
  63. protected Dictionary<UUID, TaskInventoryItem> m_scripts = null;
  64. /// <summary>
  65. /// Tracks whether inventory has changed since the last persistent backup
  66. /// </summary>
  67. internal bool HasInventoryChanged;
  68. /// <value>
  69. /// Inventory serial number
  70. /// </value>
  71. protected internal uint Serial
  72. {
  73. get { return m_inventorySerial; }
  74. set { m_inventorySerial = value; }
  75. }
  76. /// <value>
  77. /// Raw inventory data
  78. /// </value>
  79. protected internal TaskInventoryDictionary Items
  80. {
  81. get
  82. {
  83. return m_items;
  84. }
  85. set
  86. {
  87. m_items = value;
  88. m_inventorySerial++;
  89. gatherScriptsAndQueryStates();
  90. }
  91. }
  92. public int Count
  93. {
  94. get
  95. {
  96. m_items.LockItemsForRead(true);
  97. int c = m_items.Count;
  98. m_items.LockItemsForRead(false);
  99. return c;
  100. }
  101. }
  102. /// <summary>
  103. /// Constructor
  104. /// </summary>
  105. /// <param name="part">
  106. /// A <see cref="SceneObjectPart"/>
  107. /// </param>
  108. public SceneObjectPartInventory(SceneObjectPart part)
  109. {
  110. m_part = part;
  111. }
  112. ~SceneObjectPartInventory()
  113. {
  114. Dispose(false);
  115. }
  116. private bool disposed = false;
  117. public void Dispose()
  118. {
  119. Dispose(true);
  120. GC.SuppressFinalize(this);
  121. }
  122. protected void Dispose(bool disposing)
  123. {
  124. // Check to see if Dispose has already been called.
  125. if (!disposed)
  126. {
  127. if (m_items != null)
  128. {
  129. m_items.Dispose();
  130. m_items = null;
  131. }
  132. disposed = true;
  133. }
  134. }
  135. /// <summary>
  136. /// Force the task inventory of this prim to persist at the next update sweep
  137. /// </summary>
  138. public void ForceInventoryPersistence()
  139. {
  140. HasInventoryChanged = true;
  141. }
  142. /// <summary>
  143. /// Reset UUIDs for all the items in the prim's inventory.
  144. /// </summary>
  145. /// <remarks>
  146. /// This involves either generating
  147. /// new ones or setting existing UUIDs to the correct parent UUIDs.
  148. ///
  149. /// If this method is called and there are inventory items, then we regard the inventory as having changed.
  150. /// </remarks>
  151. public void ResetInventoryIDs()
  152. {
  153. if (m_part == null)
  154. return;
  155. m_items.LockItemsForWrite(true);
  156. if (m_items.Count == 0)
  157. {
  158. m_items.LockItemsForWrite(false);
  159. return;
  160. }
  161. UUID partID = m_part.UUID;
  162. IList<TaskInventoryItem> items = new List<TaskInventoryItem>(m_items.Values);
  163. m_items.Clear();
  164. if(m_scripts == null)
  165. {
  166. for (int i = 0; i < items.Count; ++i)
  167. {
  168. TaskInventoryItem item = items[i];
  169. item.ResetIDs(partID);
  170. m_items.Add(item.ItemID, item);
  171. }
  172. }
  173. else
  174. {
  175. m_scripts.Clear();
  176. for (int i = 0; i < items.Count; ++i)
  177. {
  178. TaskInventoryItem item = items[i];
  179. item.ResetIDs(partID);
  180. m_items.Add(item.ItemID, item);
  181. if (item.InvType == (int)InventoryType.LSL)
  182. m_scripts.Add(item.ItemID, item);
  183. }
  184. }
  185. m_inventorySerial++;
  186. m_items.LockItemsForWrite(false);
  187. }
  188. public void ResetObjectID()
  189. {
  190. if (m_part == null)
  191. return;
  192. UUID partID = m_part.UUID;
  193. m_items.LockItemsForWrite(true);
  194. if (m_items.Count == 0)
  195. {
  196. m_items.LockItemsForWrite(false);
  197. return;
  198. }
  199. foreach(TaskInventoryItem item in m_items.Values)
  200. {
  201. item.ParentPartID = partID;
  202. item.ParentID = partID;
  203. }
  204. m_inventorySerial++;
  205. m_items.LockItemsForWrite(false);
  206. }
  207. /// <summary>
  208. /// Change every item in this inventory to a new owner.
  209. /// </summary>
  210. /// <param name="ownerId"></param>
  211. public void ChangeInventoryOwner(UUID ownerId)
  212. {
  213. if(m_part == null)
  214. return;
  215. m_items.LockItemsForWrite(true);
  216. if (m_items.Count == 0)
  217. {
  218. m_items.LockItemsForWrite(false);
  219. return;
  220. }
  221. foreach (TaskInventoryItem item in m_items.Values)
  222. {
  223. if (ownerId != item.OwnerID)
  224. item.LastOwnerID = item.OwnerID;
  225. item.OwnerID = ownerId;
  226. item.PermsMask = 0;
  227. item.PermsGranter = UUID.Zero;
  228. item.OwnerChanged = true;
  229. }
  230. HasInventoryChanged = true;
  231. m_part.ParentGroup.HasGroupChanged = true;
  232. m_inventorySerial++;
  233. m_items.LockItemsForWrite(false);
  234. }
  235. /// <summary>
  236. /// Change every item in this inventory to a new group.
  237. /// </summary>
  238. /// <param name="groupID"></param>
  239. public void ChangeInventoryGroup(UUID groupID)
  240. {
  241. if(m_part == null)
  242. return;
  243. m_items.LockItemsForWrite(true);
  244. if (m_items.Count == 0)
  245. {
  246. m_items.LockItemsForWrite(false);
  247. return;
  248. }
  249. m_inventorySerial++;
  250. // Don't let this set the HasGroupChanged flag for attachments
  251. // as this happens during rez and we don't want a new asset
  252. // for each attachment each time
  253. if (!m_part.ParentGroup.IsAttachment)
  254. {
  255. HasInventoryChanged = true;
  256. m_part.ParentGroup.HasGroupChanged = true;
  257. }
  258. foreach (TaskInventoryItem item in m_items.Values)
  259. item.GroupID = groupID;
  260. m_items.LockItemsForWrite(false);
  261. }
  262. private void gatherScriptsAndQueryStates()
  263. {
  264. m_items.LockItemsForWrite(true);
  265. m_scripts = new Dictionary<UUID, TaskInventoryItem>();
  266. foreach (TaskInventoryItem item in m_items.Values)
  267. {
  268. if (item.InvType == (int)InventoryType.LSL)
  269. m_scripts[item.ItemID] = item;
  270. }
  271. if (m_scripts.Count == 0)
  272. {
  273. m_items.LockItemsForWrite(false);
  274. m_scripts = null;
  275. return;
  276. }
  277. m_items.LockItemsForWrite(false);
  278. if (m_part.ParentGroup == null || m_part.ParentGroup.Scene == null)
  279. return;
  280. IScriptModule[] scriptEngines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
  281. if (scriptEngines.Length == 0) // No engine at all
  282. return;
  283. bool running;
  284. m_items.LockItemsForRead(true);
  285. foreach (TaskInventoryItem item in m_scripts.Values)
  286. {
  287. //running = false;
  288. foreach (IScriptModule e in scriptEngines)
  289. {
  290. if (e.HasScript(item.ItemID, out running))
  291. {
  292. item.ScriptRunning = running;
  293. break;
  294. }
  295. }
  296. //item.ScriptRunning = running;
  297. }
  298. m_items.LockItemsForRead(false);
  299. }
  300. public bool TryGetScriptInstanceRunning(UUID itemId, out bool running)
  301. {
  302. running = false;
  303. TaskInventoryItem item = GetInventoryItem(itemId);
  304. if (item == null)
  305. return false;
  306. return TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running);
  307. }
  308. public static bool TryGetScriptInstanceRunning(Scene scene, TaskInventoryItem item, out bool running)
  309. {
  310. running = false;
  311. if (item.InvType != (int)InventoryType.LSL)
  312. return false;
  313. IScriptModule[] scriptEngines = scene.RequestModuleInterfaces<IScriptModule>();
  314. if (scriptEngines.Length == 0) // No engine at all
  315. return false;
  316. foreach (IScriptModule e in scriptEngines)
  317. {
  318. if (e.HasScript(item.ItemID, out running))
  319. return true;
  320. }
  321. return false;
  322. }
  323. public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
  324. {
  325. m_items.LockItemsForRead(true);
  326. if(m_scripts == null || m_scripts.Count == 0)
  327. {
  328. m_items.LockItemsForRead(false);
  329. return 0;
  330. }
  331. List<TaskInventoryItem> scripts = new List<TaskInventoryItem>(m_scripts.Values);
  332. m_items.LockItemsForRead(false);
  333. int scriptsValidForStarting = 0;
  334. for (int i = 0; i < scripts.Count; ++i)
  335. {
  336. if (CreateScriptInstance(scripts[i], startParam, postOnRez, engine, stateSource))
  337. scriptsValidForStarting++;
  338. }
  339. return scriptsValidForStarting;
  340. }
  341. public ArrayList GetScriptErrors(UUID itemID)
  342. {
  343. IScriptModule[] scriptEngines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
  344. ArrayList ret = new ArrayList();
  345. foreach (IScriptModule e in scriptEngines)
  346. {
  347. if (e != null)
  348. {
  349. ArrayList errors = e.GetScriptErrors(itemID);
  350. foreach (Object line in errors)
  351. ret.Add(line);
  352. }
  353. }
  354. return ret;
  355. }
  356. /// <summary>
  357. /// Stop and remove all the scripts in this prim.
  358. /// </summary>
  359. /// <param name="sceneObjectBeingDeleted">
  360. /// Should be true if these scripts are being removed because the scene
  361. /// object is being deleted. This will prevent spurious updates to the client.
  362. /// </param>
  363. public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
  364. {
  365. m_items.LockItemsForRead(true);
  366. if (m_scripts == null || m_scripts.Count == 0)
  367. {
  368. m_items.LockItemsForRead(false);
  369. return;
  370. }
  371. List<TaskInventoryItem> scripts = new List<TaskInventoryItem>(m_scripts.Values);
  372. m_items.LockItemsForRead(false);
  373. foreach (TaskInventoryItem item in scripts)
  374. {
  375. RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
  376. m_part.RemoveScriptEvents(item.ItemID);
  377. }
  378. }
  379. /// <summary>
  380. /// Stop all the scripts in this prim.
  381. /// </summary>
  382. public void StopScriptInstances()
  383. {
  384. m_items.LockItemsForRead(true);
  385. if (m_scripts == null || m_scripts.Count == 0)
  386. {
  387. m_items.LockItemsForRead(false);
  388. return;
  389. }
  390. List<TaskInventoryItem> scripts = new List<TaskInventoryItem>(m_scripts.Values);
  391. m_items.LockItemsForRead(false);
  392. foreach (TaskInventoryItem item in scripts)
  393. StopScriptInstance(item);
  394. }
  395. /// <summary>
  396. /// Start a script which is in this prim's inventory.
  397. /// </summary>
  398. /// <param name="item"></param>
  399. /// <returns>true if the script instance was created, false otherwise</returns>
  400. public bool CreateScriptInstance(TaskInventoryItem item, int startParam, bool postOnRez, string engine, int stateSource)
  401. {
  402. //m_log.DebugFormat("[PRIM INVENTORY]: Starting script {0} {1} in prim {2} {3} in {4}",
  403. // item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName);
  404. if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item, m_part))
  405. {
  406. StoreScriptError(item.ItemID, "no permission");
  407. return false;
  408. }
  409. m_part.AddFlag(PrimFlags.Scripted);
  410. if (m_part.ParentGroup.Scene.RegionInfo.RegionSettings.DisableScripts)
  411. return false;
  412. UUID itemID = item.ItemID;
  413. m_items.LockItemsForRead(true);
  414. if (!m_items.TryGetValue(item.ItemID, out TaskInventoryItem it))
  415. {
  416. m_items.LockItemsForRead(false);
  417. StoreScriptError(itemID, String.Format("TaskItem ID {0} could not be found", item.ItemID));
  418. m_log.ErrorFormat(
  419. "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since taskitem ID {4} could not be found",
  420. item.Name, item.ItemID, m_part.AbsolutePosition,
  421. m_part.ParentGroup.Scene.RegionInfo.RegionName, item.ItemID);
  422. return false;
  423. }
  424. m_items.LockItemsForRead(false);
  425. if (stateSource == 2 && m_part.ParentGroup.Scene.m_trustBinaries)
  426. {
  427. // Prim crossing
  428. m_items.LockItemsForWrite(true);
  429. it.PermsMask = 0;
  430. it.PermsGranter = UUID.Zero;
  431. m_items.LockItemsForWrite(false);
  432. m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
  433. m_part.LocalId, itemID, String.Empty, startParam, postOnRez, engine, stateSource);
  434. StoreScriptErrors(itemID, null);
  435. m_part.ParentGroup.AddActiveScriptCount(1);
  436. m_part.ScheduleFullUpdate();
  437. return true;
  438. }
  439. AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
  440. if (asset == null)
  441. {
  442. StoreScriptError(itemID, String.Format("asset ID {0} could not be found", item.AssetID));
  443. m_log.ErrorFormat(
  444. "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
  445. item.Name, item.ItemID, m_part.AbsolutePosition,
  446. m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID);
  447. return false;
  448. }
  449. if (m_part.ParentGroup.m_savedScriptState != null)
  450. item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, itemID);
  451. m_items.LockItemsForWrite(true);
  452. it.OldItemID = item.OldItemID;
  453. it.PermsMask = 0;
  454. it.PermsGranter = UUID.Zero;
  455. m_items.LockItemsForWrite(false);
  456. string script = Utils.BytesToString(asset.Data);
  457. m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
  458. m_part.LocalId, itemID, script, startParam, postOnRez, engine, stateSource);
  459. StoreScriptErrors(itemID, null);
  460. //if (item.ScriptRunning)
  461. m_part.ParentGroup.AddActiveScriptCount(1);
  462. return true;
  463. }
  464. private UUID RestoreSavedScriptState(UUID loadedID, UUID oldID, UUID newID)
  465. {
  466. //m_log.DebugFormat(
  467. // "[PRIM INVENTORY]: Restoring scripted state for item {0}, oldID {1}, loadedID {2}",
  468. // newID, oldID, loadedID);
  469. IScriptModule[] scriptEngines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
  470. if (scriptEngines.Length == 0) // No engine at all
  471. return oldID;
  472. UUID stateID = oldID;
  473. if (!m_part.ParentGroup.m_savedScriptState.ContainsKey(oldID))
  474. stateID = loadedID;
  475. if (m_part.ParentGroup.m_savedScriptState.ContainsKey(stateID))
  476. {
  477. XmlDocument doc = new XmlDocument();
  478. doc.LoadXml(m_part.ParentGroup.m_savedScriptState[stateID]);
  479. ////////// CRUFT WARNING ///////////////////////////////////
  480. //
  481. // Old objects will have <ScriptState><State> ...
  482. // This format is XEngine ONLY
  483. //
  484. // New objects have <State Engine="...." ...><ScriptState>...
  485. // This can be passed to any engine
  486. //
  487. XmlNode n = doc.SelectSingleNode("ScriptState");
  488. if (n != null) // Old format data
  489. {
  490. XmlDocument newDoc = new XmlDocument();
  491. XmlElement rootN = newDoc.CreateElement("", "State", "");
  492. XmlAttribute uuidA = newDoc.CreateAttribute("", "UUID", "");
  493. uuidA.Value = stateID.ToString();
  494. rootN.Attributes.Append(uuidA);
  495. XmlAttribute engineA = newDoc.CreateAttribute("", "Engine", "");
  496. engineA.Value = "XEngine";
  497. rootN.Attributes.Append(engineA);
  498. newDoc.AppendChild(rootN);
  499. XmlNode stateN = newDoc.ImportNode(n, true);
  500. rootN.AppendChild(stateN);
  501. // This created document has only the minimun data
  502. // necessary for XEngine to parse it successfully
  503. //m_log.DebugFormat("[PRIM INVENTORY]: Adding legacy state {0} in {1}", stateID, newID);
  504. m_part.ParentGroup.m_savedScriptState[stateID] = newDoc.OuterXml;
  505. }
  506. foreach (IScriptModule e in scriptEngines)
  507. {
  508. if (e != null)
  509. {
  510. if (e.SetXMLState(newID, m_part.ParentGroup.m_savedScriptState[stateID]))
  511. break;
  512. }
  513. }
  514. m_part.ParentGroup.m_savedScriptState.Remove(stateID);
  515. }
  516. return stateID;
  517. }
  518. /// <summary>
  519. /// Start a script which is in this prim's inventory.
  520. /// Some processing may occur in the background, but this routine returns asap.
  521. /// </summary>
  522. /// <param name="itemId">
  523. /// A <see cref="UUID"/>
  524. /// </param>
  525. public bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
  526. {
  527. lock (m_scriptErrors)
  528. {
  529. // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
  530. m_scriptErrors.Remove(itemId);
  531. }
  532. CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
  533. return true;
  534. }
  535. private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
  536. {
  537. m_items.LockItemsForRead(true);
  538. if (m_items.TryGetValue(itemId, out TaskInventoryItem it))
  539. {
  540. m_items.LockItemsForRead(false);
  541. CreateScriptInstance(it, startParam, postOnRez, engine, stateSource);
  542. }
  543. else
  544. {
  545. m_items.LockItemsForRead(false);
  546. string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
  547. m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
  548. StoreScriptError(itemId, msg);
  549. m_log.ErrorFormat(
  550. "[PRIM INVENTORY]: " +
  551. "Couldn't start script with ID {0} since it {1}", itemId, msg);
  552. }
  553. }
  554. /// <summary>
  555. /// Start a script which is in this prim's inventory and return any compilation error messages.
  556. /// </summary>
  557. /// <param name="itemId">
  558. /// A <see cref="UUID"/>
  559. /// </param>
  560. public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
  561. {
  562. ArrayList errors;
  563. // Indicate to CreateScriptInstanceInternal() we want it to
  564. // post any compilation/loading error messages
  565. lock (m_scriptErrors)
  566. {
  567. m_scriptErrors[itemId] = null;
  568. }
  569. // Perform compilation/loading
  570. CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
  571. // Wait for and retrieve any errors
  572. lock (m_scriptErrors)
  573. {
  574. while ((errors = m_scriptErrors[itemId]) == null)
  575. {
  576. if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
  577. {
  578. m_log.ErrorFormat(
  579. "[PRIM INVENTORY]: " +
  580. "timedout waiting for script {0} errors", itemId);
  581. errors = m_scriptErrors[itemId];
  582. if (errors == null)
  583. {
  584. errors = new ArrayList(1);
  585. errors.Add("timedout waiting for errors");
  586. }
  587. break;
  588. }
  589. }
  590. m_scriptErrors.Remove(itemId);
  591. }
  592. return errors;
  593. }
  594. // Signal to CreateScriptInstanceEr() that compilation/loading is complete
  595. private void StoreScriptErrors(UUID itemId, ArrayList errors)
  596. {
  597. lock (m_scriptErrors)
  598. {
  599. // If compilation/loading initiated via CreateScriptInstance(),
  600. // it does not want the errors, so just get out
  601. if (!m_scriptErrors.ContainsKey(itemId))
  602. {
  603. return;
  604. }
  605. // Initiated via CreateScriptInstanceEr(), if we know what the
  606. // errors are, save them and wake CreateScriptInstanceEr().
  607. if (errors != null)
  608. {
  609. m_scriptErrors[itemId] = errors;
  610. System.Threading.Monitor.PulseAll(m_scriptErrors);
  611. return;
  612. }
  613. }
  614. // Initiated via CreateScriptInstanceEr() but we don't know what
  615. // the errors are yet, so retrieve them from the script engine.
  616. // This may involve some waiting internal to GetScriptErrors().
  617. errors = GetScriptErrors(itemId);
  618. // Get a default non-null value to indicate success.
  619. if (errors == null)
  620. {
  621. errors = new ArrayList();
  622. }
  623. // Post to CreateScriptInstanceEr() and wake it up
  624. lock (m_scriptErrors)
  625. {
  626. m_scriptErrors[itemId] = errors;
  627. System.Threading.Monitor.PulseAll(m_scriptErrors);
  628. }
  629. }
  630. // Like StoreScriptErrors(), but just posts a single string message
  631. private void StoreScriptError(UUID itemId, string message)
  632. {
  633. ArrayList errors = new ArrayList(1);
  634. errors.Add(message);
  635. StoreScriptErrors(itemId, errors);
  636. }
  637. /// <summary>
  638. /// Stop and remove a script which is in this prim's inventory.
  639. /// </summary>
  640. /// <param name="itemId"></param>
  641. /// <param name="sceneObjectBeingDeleted">
  642. /// Should be true if this script is being removed because the scene
  643. /// object is being deleted. This will prevent spurious updates to the client.
  644. /// </param>
  645. public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
  646. {
  647. if (m_items.ContainsKey(itemId))
  648. {
  649. if (!sceneObjectBeingDeleted)
  650. m_part.RemoveScriptEvents(itemId);
  651. m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemId);
  652. m_part.ParentGroup.AddActiveScriptCount(-1);
  653. }
  654. else
  655. {
  656. m_log.WarnFormat(
  657. "[PRIM INVENTORY]: " +
  658. "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
  659. itemId, m_part.Name, m_part.UUID,
  660. m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
  661. }
  662. }
  663. /// <summary>
  664. /// Stop a script which is in this prim's inventory.
  665. /// </summary>
  666. /// <param name="itemId"></param>
  667. /// <param name="sceneObjectBeingDeleted">
  668. /// Should be true if this script is being removed because the scene
  669. /// object is being deleted. This will prevent spurious updates to the client.
  670. /// </param>
  671. public void StopScriptInstance(UUID itemId)
  672. {
  673. m_items.LockItemsForRead(true);
  674. m_items.TryGetValue(itemId, out TaskInventoryItem scriptItem);
  675. m_items.LockItemsForRead(false);
  676. if (scriptItem != null)
  677. {
  678. StopScriptInstance(scriptItem);
  679. }
  680. else
  681. {
  682. m_log.WarnFormat(
  683. "[PRIM INVENTORY]: " +
  684. "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
  685. itemId, m_part.Name, m_part.UUID,
  686. m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
  687. }
  688. }
  689. /// <summary>
  690. /// Stop a script which is in this prim's inventory.
  691. /// </summary>
  692. /// <param name="itemId"></param>
  693. /// <param name="sceneObjectBeingDeleted">
  694. /// Should be true if this script is being removed because the scene
  695. /// object is being deleted. This will prevent spurious updates to the client.
  696. /// </param>
  697. public void StopScriptInstance(TaskInventoryItem item)
  698. {
  699. if (m_part.ParentGroup.Scene != null)
  700. m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID);
  701. // At the moment, even stopped scripts are counted as active, which is probably wrong.
  702. // m_part.ParentGroup.AddActiveScriptCount(-1);
  703. }
  704. public void SendReleaseScriptsControl()
  705. {
  706. m_items.LockItemsForRead(true);
  707. if (m_scripts == null || m_scripts.Count == 0)
  708. {
  709. m_items.LockItemsForRead(false);
  710. return;
  711. }
  712. List<UUID> grants = new List<UUID>();
  713. List<UUID> items = new List<UUID>();
  714. foreach (TaskInventoryItem item in m_scripts.Values)
  715. {
  716. if (((item.PermsMask & 4) == 0))
  717. continue;
  718. grants.Add(item.PermsGranter);
  719. items.Add(item.ItemID);
  720. }
  721. m_items.LockItemsForRead(false);
  722. if (grants.Count > 0)
  723. {
  724. for (int i = 0; i < grants.Count; ++i)
  725. {
  726. ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(grants[i]);
  727. if (presence != null && !presence.IsDeleted && presence.ParentPart != m_part) // last check mb needed for vehicle crossing ???
  728. presence.UnRegisterControlEventsToScript(m_part.LocalId, items[i]);
  729. }
  730. }
  731. }
  732. public void RemoveScriptsPermissions(int permissions)
  733. {
  734. m_items.LockItemsForWrite(true);
  735. if (m_scripts == null || m_scripts.Count == 0)
  736. {
  737. m_items.LockItemsForWrite(false);
  738. return;
  739. }
  740. bool removeControl = ((permissions & 4) != 0); //takecontrol
  741. List<UUID> grants = new List<UUID>();
  742. List<UUID> items = new List<UUID>();
  743. permissions = ~permissions;
  744. foreach (TaskInventoryItem item in m_scripts.Values)
  745. {
  746. int curmask = item.PermsMask;
  747. UUID curGrant = item.PermsGranter;
  748. if (removeControl && ((curmask & 4) != 0))
  749. {
  750. grants.Add(curGrant);
  751. items.Add(item.ItemID);
  752. }
  753. curmask &= permissions;
  754. item.PermsMask = curmask;
  755. if(curmask == 0)
  756. item.PermsGranter = UUID.Zero;
  757. }
  758. m_items.LockItemsForWrite(false);
  759. if(grants.Count > 0)
  760. {
  761. for(int i = 0; i< grants.Count;++i)
  762. {
  763. ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(grants[i]);
  764. if (presence != null && !presence.IsDeleted)
  765. presence.UnRegisterControlEventsToScript(m_part.LocalId, items[i]);
  766. }
  767. }
  768. }
  769. public void RemoveScriptsPermissions(ScenePresence sp, int permissions)
  770. {
  771. m_items.LockItemsForWrite(true);
  772. if (m_scripts == null || m_scripts.Count == 0)
  773. {
  774. m_items.LockItemsForWrite(false);
  775. return;
  776. }
  777. bool removeControl = ((permissions & 4) != 0); //takecontrol
  778. UUID grant = sp.UUID;
  779. List<UUID> items = new List<UUID>();
  780. permissions = ~permissions;
  781. foreach (TaskInventoryItem item in m_scripts.Values)
  782. {
  783. if(grant != item.PermsGranter)
  784. continue;
  785. int curmask = item.PermsMask;
  786. if (removeControl && ((curmask & 4) != 0))
  787. items.Add(item.ItemID);
  788. curmask &= permissions;
  789. item.PermsMask = curmask;
  790. if(curmask == 0)
  791. item.PermsGranter = UUID.Zero;
  792. }
  793. m_items.LockItemsForWrite(false);
  794. if(items.Count > 0)
  795. {
  796. for(int i = 0; i < items.Count; ++i)
  797. {
  798. if (!sp.IsDeleted)
  799. sp.UnRegisterControlEventsToScript(m_part.LocalId, items[i]);
  800. }
  801. }
  802. }
  803. /// <summary>
  804. /// Check if the inventory holds an item with a given name.
  805. /// </summary>
  806. /// <param name="name"></param>
  807. /// <returns></returns>
  808. private bool InventoryContainsName(string name)
  809. {
  810. m_items.LockItemsForRead(true);
  811. foreach (TaskInventoryItem item in m_items.Values)
  812. {
  813. if (item.Name == name)
  814. {
  815. m_items.LockItemsForRead(false);
  816. return true;
  817. }
  818. }
  819. m_items.LockItemsForRead(false);
  820. return false;
  821. }
  822. /// <summary>
  823. /// For a given item name, return that name if it is available. Otherwise, return the next available
  824. /// similar name (which is currently the original name with the next available numeric suffix).
  825. /// </summary>
  826. /// <param name="name"></param>
  827. /// <returns></returns>
  828. private string FindAvailableInventoryName(string name)
  829. {
  830. if (!InventoryContainsName(name))
  831. return name;
  832. int suffix=1;
  833. while (suffix < 256)
  834. {
  835. string tryName=String.Format("{0} {1}", name, suffix);
  836. if (!InventoryContainsName(tryName))
  837. return tryName;
  838. suffix++;
  839. }
  840. return String.Empty;
  841. }
  842. /// <summary>
  843. /// Add an item to this prim's inventory. If an item with the same name already exists, then an alternative
  844. /// name is chosen.
  845. /// </summary>
  846. /// <param name="item"></param>
  847. public void AddInventoryItem(TaskInventoryItem item, bool allowedDrop)
  848. {
  849. AddInventoryItem(item.Name, item, allowedDrop);
  850. }
  851. /// <summary>
  852. /// Add an item to this prim's inventory. If an item with the same name already exists, it is replaced.
  853. /// </summary>
  854. /// <param name="item"></param>
  855. public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
  856. {
  857. m_items.LockItemsForRead(true);
  858. List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
  859. m_items.LockItemsForRead(false);
  860. foreach (TaskInventoryItem i in il)
  861. {
  862. if (i.Name == item.Name)
  863. {
  864. if (i.InvType == (int)InventoryType.LSL)
  865. RemoveScriptInstance(i.ItemID, false);
  866. RemoveInventoryItem(i.ItemID);
  867. break;
  868. }
  869. }
  870. AddInventoryItem(item.Name, item, allowedDrop);
  871. }
  872. /// <summary>
  873. /// Add an item to this prim's inventory.
  874. /// </summary>
  875. /// <param name="name">The name that the new item should have.</param>
  876. /// <param name="item">
  877. /// The item itself. The name within this structure is ignored in favour of the name
  878. /// given in this method's arguments
  879. /// </param>
  880. /// <param name="allowedDrop">
  881. /// Item was only added to inventory because AllowedDrop is set
  882. /// </param>
  883. protected void AddInventoryItem(string name, TaskInventoryItem item, bool allowedDrop)
  884. {
  885. name = FindAvailableInventoryName(name);
  886. if (name.Length == 0)
  887. return;
  888. item.ParentID = m_part.UUID;
  889. item.ParentPartID = m_part.UUID;
  890. item.Name = name;
  891. item.GroupID = m_part.GroupID;
  892. m_items.LockItemsForWrite(true);
  893. m_items.Add(item.ItemID, item);
  894. if (item.InvType == (int)InventoryType.LSL)
  895. {
  896. if (m_scripts == null)
  897. m_scripts = new Dictionary<UUID, TaskInventoryItem>();
  898. m_scripts.Add(item.ItemID, item);
  899. }
  900. m_items.LockItemsForWrite(false);
  901. if (allowedDrop)
  902. m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP, item.ItemID);
  903. else
  904. m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
  905. m_part.AggregateInnerPerms();
  906. m_inventorySerial++;
  907. HasInventoryChanged = true;
  908. m_part.ParentGroup.HasGroupChanged = true;
  909. }
  910. /// <summary>
  911. /// Restore a whole collection of items to the prim's inventory at once.
  912. /// We assume that the items already have all their fields correctly filled out.
  913. /// The items are not flagged for persistence to the database, since they are being restored
  914. /// from persistence rather than being newly added.
  915. /// </summary>
  916. /// <param name="items"></param>
  917. public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
  918. {
  919. m_items.LockItemsForWrite(true);
  920. foreach (TaskInventoryItem item in items)
  921. {
  922. m_items.Add(item.ItemID, item);
  923. if (item.InvType == (int)InventoryType.LSL)
  924. {
  925. if (m_scripts == null)
  926. m_scripts = new Dictionary<UUID, TaskInventoryItem>();
  927. m_scripts.Add(item.ItemID, item);
  928. }
  929. }
  930. m_items.LockItemsForWrite(false);
  931. m_part.AggregateInnerPerms();
  932. m_inventorySerial++;
  933. }
  934. /// <summary>
  935. /// Returns an existing inventory item. Returns the original, so any changes will be live.
  936. /// </summary>
  937. /// <param name="itemID"></param>
  938. /// <returns>null if the item does not exist</returns>
  939. public TaskInventoryItem GetInventoryItem(UUID itemId)
  940. {
  941. TaskInventoryItem item;
  942. m_items.LockItemsForRead(true);
  943. m_items.TryGetValue(itemId, out item);
  944. m_items.LockItemsForRead(false);
  945. return item;
  946. }
  947. public TaskInventoryItem GetInventoryItem(string name)
  948. {
  949. m_items.LockItemsForRead(true);
  950. foreach (TaskInventoryItem item in m_items.Values)
  951. {
  952. if (item.Name == name)
  953. {
  954. m_items.LockItemsForRead(false);
  955. return item;
  956. }
  957. }
  958. m_items.LockItemsForRead(false);
  959. return null;
  960. }
  961. public TaskInventoryItem GetInventoryItem(string name, int type)
  962. {
  963. m_items.LockItemsForRead(true);
  964. foreach (TaskInventoryItem item in m_items.Values)
  965. {
  966. if (item.Type == type && item.Name == name)
  967. {
  968. m_items.LockItemsForRead(false);
  969. return item;
  970. }
  971. }
  972. m_items.LockItemsForRead(false);
  973. return null;
  974. }
  975. public List<TaskInventoryItem> GetInventoryItems(string name)
  976. {
  977. List<TaskInventoryItem> items = new List<TaskInventoryItem>();
  978. m_items.LockItemsForRead(true);
  979. foreach (TaskInventoryItem item in m_items.Values)
  980. {
  981. if (item.Name == name)
  982. items.Add(item);
  983. }
  984. m_items.LockItemsForRead(false);
  985. return items;
  986. }
  987. public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist, out Vector3 bbox, out float offsetHeight)
  988. {
  989. return GetRezReadySceneObjects(item, item.OwnerID, m_part.GroupID, out objlist, out veclist, out bbox, out offsetHeight);
  990. }
  991. public bool GetRezReadySceneObjects(TaskInventoryItem item, UUID NewOwner, UUID NewGroup, out List<SceneObjectGroup> objlist, out List<Vector3> veclist, out Vector3 bbox, out float offsetHeight)
  992. {
  993. AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
  994. if (null == rezAsset)
  995. {
  996. m_log.WarnFormat(
  997. "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}",
  998. item.AssetID, item.Name, m_part.Name);
  999. objlist = null;
  1000. veclist = null;
  1001. bbox = Vector3.Zero;
  1002. offsetHeight = 0;
  1003. return false;
  1004. }
  1005. m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
  1006. for (int i = 0; i < objlist.Count; i++)
  1007. {
  1008. SceneObjectGroup group = objlist[i];
  1009. /*
  1010. group.RootPart.AttachPoint = group.RootPart.Shape.State;
  1011. group.RootPart.AttachedPos = group.AbsolutePosition;
  1012. group.RootPart.AttachRotation = group.GroupRotation;
  1013. */
  1014. group.ResetIDs();
  1015. SceneObjectPart rootPart = group.GetPart(group.UUID);
  1016. // Since renaming the item in the inventory does not affect the name stored
  1017. // in the serialization, transfer the correct name from the inventory to the
  1018. // object itself before we rez.
  1019. // Only do these for the first object if we are rezzing a coalescence.
  1020. // nahh dont mess with coalescence objects,
  1021. // the name in inventory can be change for inventory purpuses only
  1022. if (objlist.Count == 1)
  1023. {
  1024. rootPart.Name = item.Name;
  1025. rootPart.Description = item.Description;
  1026. }
  1027. group.SetGroup(NewGroup, null);
  1028. SceneObjectPart[] partList = group.Parts;
  1029. bool slamThings = (item.CurrentPermissions & (uint)PermissionMask.Slam) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0;
  1030. if ((rootPart.OwnerID != NewOwner) || slamThings)
  1031. {
  1032. if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
  1033. {
  1034. foreach (SceneObjectPart part in partList)
  1035. {
  1036. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
  1037. part.EveryoneMask = item.EveryonePermissions;
  1038. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
  1039. part.NextOwnerMask = item.NextPermissions;
  1040. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
  1041. part.GroupMask = item.GroupPermissions;
  1042. }
  1043. group.ApplyNextOwnerPermissions();
  1044. }
  1045. }
  1046. foreach (SceneObjectPart part in partList)
  1047. {
  1048. if ((part.OwnerID.NotEqual(NewOwner)))
  1049. {
  1050. if(part.GroupID.NotEqual(part.OwnerID))
  1051. part.LastOwnerID = part.OwnerID;
  1052. part.OwnerID = NewOwner;
  1053. part.Inventory.ChangeInventoryOwner(NewOwner);
  1054. }
  1055. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
  1056. part.EveryoneMask = item.EveryonePermissions;
  1057. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
  1058. part.NextOwnerMask = item.NextPermissions;
  1059. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
  1060. part.GroupMask = item.GroupPermissions;
  1061. }
  1062. rootPart.TrimPermissions();
  1063. group.InvalidateDeepEffectivePerms();
  1064. }
  1065. return true;
  1066. }
  1067. public SceneObjectGroup GetSingleRezReadySceneObject(TaskInventoryItem item, UUID NewOwner, UUID NewGroup)
  1068. {
  1069. AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
  1070. if (rezAsset is null)
  1071. {
  1072. m_log.Warn($"[PRIM INVENTORY]: Could not find asset {item.AssetID} for inventory item {item.Name} in {m_part.Name}");
  1073. return null;
  1074. }
  1075. SceneObjectGroup group = m_part.ParentGroup.Scene.GetSingleObjectToRez(rezAsset.Data);
  1076. if (group == null)
  1077. return null;
  1078. group.ResetIDs();
  1079. SceneObjectPart rootPart = group.RootPart;
  1080. rootPart.Name = item.Name;
  1081. rootPart.Description = item.Description;
  1082. group.SetGroup(NewGroup, null);
  1083. SceneObjectPart[] partList = group.Parts;
  1084. bool slamThings = (item.CurrentPermissions & (uint)PermissionMask.Slam) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0;
  1085. if (slamThings || rootPart.OwnerID.NotEqual(NewOwner))
  1086. {
  1087. if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
  1088. {
  1089. foreach (SceneObjectPart part in partList)
  1090. {
  1091. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
  1092. part.EveryoneMask = item.EveryonePermissions;
  1093. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
  1094. part.NextOwnerMask = item.NextPermissions;
  1095. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
  1096. part.GroupMask = item.GroupPermissions;
  1097. }
  1098. group.ApplyNextOwnerPermissions();
  1099. }
  1100. }
  1101. foreach (SceneObjectPart part in partList)
  1102. {
  1103. if (part.OwnerID.NotEqual(NewOwner))
  1104. {
  1105. if(part.GroupID.NotEqual(part.OwnerID))
  1106. part.LastOwnerID = part.OwnerID;
  1107. part.OwnerID = NewOwner;
  1108. part.Inventory.ChangeInventoryOwner(NewOwner);
  1109. }
  1110. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
  1111. part.EveryoneMask = item.EveryonePermissions;
  1112. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
  1113. part.NextOwnerMask = item.NextPermissions;
  1114. if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
  1115. part.GroupMask = item.GroupPermissions;
  1116. }
  1117. rootPart.TrimPermissions();
  1118. group.InvalidateDeepEffectivePerms();
  1119. return group;
  1120. }
  1121. /// <summary>
  1122. /// Update an existing inventory item.
  1123. /// </summary>
  1124. /// <param name="item">The updated item. An item with the same id must already exist
  1125. /// in this prim's inventory.</param>
  1126. /// <returns>false if the item did not exist, true if the update occurred successfully</returns>
  1127. public bool UpdateInventoryItem(TaskInventoryItem item)
  1128. {
  1129. return UpdateInventoryItem(item, true, true);
  1130. }
  1131. public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents)
  1132. {
  1133. return UpdateInventoryItem(item, fireScriptEvents, true);
  1134. }
  1135. public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
  1136. {
  1137. m_items.LockItemsForWrite(true);
  1138. if (m_items.ContainsKey(item.ItemID))
  1139. {
  1140. //m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
  1141. item.ParentID = m_part.UUID;
  1142. item.ParentPartID = m_part.UUID;
  1143. // If group permissions have been set on, check that the groupID is up to date in case it has
  1144. // changed since permissions were last set.
  1145. if (item.GroupPermissions != (uint)PermissionMask.None)
  1146. item.GroupID = m_part.GroupID;
  1147. if(item.OwnerID.IsZero()) // viewer to internal enconding of group owned
  1148. item.OwnerID = item.GroupID;
  1149. if (item.AssetID.IsZero())
  1150. item.AssetID = m_items[item.ItemID].AssetID;
  1151. m_items[item.ItemID] = item;
  1152. if(item.InvType == (int)InventoryType.LSL)
  1153. {
  1154. if(m_scripts == null)
  1155. m_scripts = new Dictionary<UUID, TaskInventoryItem>();
  1156. m_scripts[item.ItemID] = item;
  1157. }
  1158. m_inventorySerial++;
  1159. if (fireScriptEvents)
  1160. m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
  1161. if (considerChanged)
  1162. {
  1163. m_part.ParentGroup.InvalidateDeepEffectivePerms();
  1164. HasInventoryChanged = true;
  1165. m_part.ParentGroup.HasGroupChanged = true;
  1166. }
  1167. m_items.LockItemsForWrite(false);
  1168. return true;
  1169. }
  1170. else
  1171. {
  1172. m_log.ErrorFormat(
  1173. "[PRIM INVENTORY]: " +
  1174. "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
  1175. item.ItemID, m_part.Name, m_part.UUID,
  1176. m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
  1177. }
  1178. m_items.LockItemsForWrite(false);
  1179. return false;
  1180. }
  1181. /// <summary>
  1182. /// Remove an item from this prim's inventory
  1183. /// </summary>
  1184. /// <param name="itemID"></param>
  1185. /// <returns>Numeric asset type of the item removed. Returns -1 if the item did not exist
  1186. /// in this prim's inventory.</returns>
  1187. public int RemoveInventoryItem(UUID itemID)
  1188. {
  1189. m_items.LockItemsForRead(true);
  1190. if (m_items.ContainsKey(itemID))
  1191. {
  1192. int type = m_items[itemID].InvType;
  1193. m_items.LockItemsForRead(false);
  1194. if (type == (int)InventoryType.LSL) // Script
  1195. {
  1196. m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
  1197. }
  1198. m_items.LockItemsForWrite(true);
  1199. m_items.Remove(itemID);
  1200. if(m_scripts != null)
  1201. {
  1202. m_scripts.Remove(itemID);
  1203. if(m_scripts.Count == 0)
  1204. m_scripts = null;
  1205. }
  1206. if (m_scripts == null)
  1207. {
  1208. m_part.RemFlag(PrimFlags.Scripted);
  1209. }
  1210. m_inventorySerial++;
  1211. m_items.LockItemsForWrite(false);
  1212. m_part.ParentGroup.InvalidateDeepEffectivePerms();
  1213. HasInventoryChanged = true;
  1214. m_part.ParentGroup.HasGroupChanged = true;
  1215. m_part.ScheduleFullUpdate();
  1216. m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
  1217. return type;
  1218. }
  1219. else
  1220. {
  1221. m_items.LockItemsForRead(false);
  1222. m_log.ErrorFormat(
  1223. "[PRIM INVENTORY]: " +
  1224. "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
  1225. itemID, m_part.Name, m_part.UUID);
  1226. }
  1227. return -1;
  1228. }
  1229. /// <summary>
  1230. /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
  1231. /// </summary>
  1232. /// <param name="xferManager"></param>
  1233. public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
  1234. {
  1235. lock (m_inventoryFileLock)
  1236. {
  1237. bool changed = false;
  1238. m_items.LockItemsForRead(true);
  1239. if (m_inventorySerial == 0) // No inventory
  1240. {
  1241. m_items.LockItemsForRead(false);
  1242. client.SendTaskInventory(m_part.UUID, 0, Array.Empty<byte>());
  1243. return;
  1244. }
  1245. if (m_items.Count == 0) // No inventory
  1246. {
  1247. m_items.LockItemsForRead(false);
  1248. client.SendTaskInventory(m_part.UUID, 0, Array.Empty<byte>());
  1249. return;
  1250. }
  1251. if (m_inventoryFileNameSerial != m_inventorySerial)
  1252. {
  1253. m_inventoryFileNameSerial = m_inventorySerial;
  1254. changed = true;
  1255. }
  1256. m_items.LockItemsForRead(false);
  1257. if (m_inventoryFileData.Length < 2)
  1258. changed = true;
  1259. int privilegedmask = 0;
  1260. bool includeAssets;
  1261. bool isVGod = client.SceneAgent is ScenePresence sp && sp.IsViewerUIGod;
  1262. if (isVGod)
  1263. {
  1264. privilegedmask = 3;
  1265. includeAssets = true;
  1266. }
  1267. else
  1268. {
  1269. includeAssets = m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId);
  1270. if(includeAssets)
  1271. privilegedmask = 1;
  1272. }
  1273. if(m_inventoryPrivileged != privilegedmask)
  1274. changed = true;
  1275. if (!changed)
  1276. {
  1277. xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
  1278. client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,
  1279. m_inventoryFileNameBytes);
  1280. return;
  1281. }
  1282. m_inventoryPrivileged = privilegedmask;
  1283. InventoryStringBuilder invString = new(m_part.UUID, UUID.Zero);
  1284. m_items.LockItemsForRead(true);
  1285. foreach (TaskInventoryItem item in m_items.Values)
  1286. {
  1287. invString.AddItemStart();
  1288. invString.AddNameValueLine("item_id", item.ItemID.ToString());
  1289. invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
  1290. invString.AddPermissionsStart();
  1291. invString.AddNameValueLine("base_mask", Utils.UIntToHexString(item.BasePermissions));
  1292. invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(item.CurrentPermissions));
  1293. invString.AddNameValueLine("group_mask", Utils.UIntToHexString(item.GroupPermissions));
  1294. invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(item.EveryonePermissions));
  1295. invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
  1296. invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
  1297. invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
  1298. invString.AddNameValueLine("group_id", item.GroupID.ToString());
  1299. if(item.GroupID.IsNotZero() && item.OwnerID.Equals(item.GroupID))
  1300. {
  1301. invString.AddNameValueLine("owner_id", UUID.ZeroString);
  1302. invString.AddNameValueLine("group_owned","1");
  1303. }
  1304. else
  1305. {
  1306. invString.AddNameValueLine("owner_id", item.OwnerID.ToString());
  1307. invString.AddNameValueLine("group_owned","0");
  1308. }
  1309. invString.AddSectionEnd();
  1310. if (includeAssets)
  1311. {
  1312. if(isVGod)
  1313. invString.AddNameValueLine("asset_id", item.AssetID.ToString());
  1314. else
  1315. {
  1316. bool allow = item.InvType switch
  1317. {
  1318. //(int)InventoryType.Sound => (item.CurrentPermissions & (uint)PermissionMask.Modify) != 0,
  1319. (int)InventoryType.Notecard => (item.CurrentPermissions & (uint)(PermissionMask.Modify | PermissionMask.Copy)) != 0,
  1320. (int)InventoryType.LSL => (item.CurrentPermissions & (uint)(PermissionMask.Modify | PermissionMask.Copy)) ==
  1321. (uint)(PermissionMask.Modify | PermissionMask.Copy),
  1322. //(int)InventoryType.Animation => (item.CurrentPermissions & (uint)PermissionMask.Modify) != 0,
  1323. //(int)InventoryType.Gesture => (item.CurrentPermissions & (uint)PermissionMask.Modify) != 0,
  1324. (int)InventoryType.Settings => (item.CurrentPermissions & (uint)(PermissionMask.Modify | PermissionMask.Copy)) ==
  1325. (uint)(PermissionMask.Modify | PermissionMask.Copy),
  1326. (int)InventoryType.Material => (item.CurrentPermissions & (uint)(PermissionMask.Modify | PermissionMask.Copy)) ==
  1327. (uint)(PermissionMask.Modify | PermissionMask.Copy),
  1328. _ => true
  1329. };
  1330. invString.AddNameValueLine("asset_id", allow ? item.AssetID.ToString() : UUID.ZeroString);
  1331. }
  1332. }
  1333. else
  1334. invString.AddNameValueLine("asset_id", UUID.ZeroString);
  1335. invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
  1336. invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
  1337. invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
  1338. invString.AddSaleStart();
  1339. invString.AddNameValueLine("sale_type", "not");
  1340. invString.AddNameValueLine("sale_price", "0");
  1341. invString.AddSectionEnd();
  1342. invString.AddNameValueLine("name", item.Name + "|");
  1343. invString.AddNameValueLine("desc", item.Description + "|");
  1344. invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
  1345. invString.AddSectionEnd();
  1346. }
  1347. m_items.LockItemsForRead(false);
  1348. m_inventoryFileData = Utils.StringToBytes(invString.GetString());
  1349. if (m_inventoryFileData.Length > 2)
  1350. {
  1351. m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
  1352. m_inventoryFileNameBytes = Util.StringToBytes256(m_inventoryFileName);
  1353. xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
  1354. client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial, m_inventoryFileNameBytes);
  1355. return;
  1356. }
  1357. client.SendTaskInventory(m_part.UUID, 0, Array.Empty<byte>());
  1358. }
  1359. }
  1360. /// <summary>
  1361. /// Process inventory backup
  1362. /// </summary>
  1363. /// <param name="datastore"></param>
  1364. public void ProcessInventoryBackup(ISimulationDataService datastore)
  1365. {
  1366. // Removed this because linking will cause an immediate delete of the new
  1367. // child prim from the database and the subsequent storing of the prim sees
  1368. // the inventory of it as unchanged and doesn't store it at all. The overhead
  1369. // of storing prim inventory needlessly is much less than the aggravation
  1370. // of prim inventory loss.
  1371. //if (HasInventoryChanged)
  1372. // {
  1373. m_items.LockItemsForRead(true);
  1374. ICollection<TaskInventoryItem> itemsvalues = m_items.Values;
  1375. HasInventoryChanged = false;
  1376. m_items.LockItemsForRead(false);
  1377. try
  1378. {
  1379. datastore.StorePrimInventory(m_part.UUID, itemsvalues);
  1380. }
  1381. catch {}
  1382. // }
  1383. }
  1384. public class InventoryStringBuilder
  1385. {
  1386. private StringBuilder BuildString = new StringBuilder(1024);
  1387. public InventoryStringBuilder(UUID folderID, UUID parentID)
  1388. {
  1389. BuildString.Append("\tinv_object\t0\n\t{\n");
  1390. AddNameValueLine("obj_id", folderID.ToString());
  1391. AddNameValueLine("parent_id", parentID.ToString());
  1392. AddNameValueLine("type", "category");
  1393. AddNameValueLine("name", "Contents|\n\t}");
  1394. }
  1395. public void AddItemStart()
  1396. {
  1397. BuildString.Append("\tinv_item\t0\n\t{\n");
  1398. }
  1399. public void AddPermissionsStart()
  1400. {
  1401. BuildString.Append("\tpermissions 0\n\t{\n");
  1402. }
  1403. public void AddSaleStart()
  1404. {
  1405. BuildString.Append("\tsale_info\t0\n\t{\n");
  1406. }
  1407. protected void AddSectionStart()
  1408. {
  1409. BuildString.Append("\t{\n");
  1410. }
  1411. public void AddSectionEnd()
  1412. {
  1413. BuildString.Append("\t}\n");
  1414. }
  1415. public void AddLine(string addLine)
  1416. {
  1417. BuildString.Append(addLine);
  1418. }
  1419. public void AddNameValueLine(ReadOnlySpan<char> name, ReadOnlySpan<char> value)
  1420. {
  1421. BuildString.Append("\t\t");
  1422. BuildString.Append(name);
  1423. BuildString.Append('\t');
  1424. BuildString.Append(value);
  1425. BuildString.Append('\n');
  1426. }
  1427. public String GetString()
  1428. {
  1429. return BuildString.ToString();
  1430. }
  1431. public void Close()
  1432. {
  1433. }
  1434. }
  1435. public void AggregateInnerPerms(ref uint owner, ref uint group, ref uint everyone)
  1436. {
  1437. foreach (TaskInventoryItem item in m_items.Values)
  1438. {
  1439. if(item.InvType == (sbyte)InventoryType.Landmark)
  1440. continue;
  1441. owner &= item.CurrentPermissions;
  1442. group &= item.GroupPermissions;
  1443. everyone &= item.EveryonePermissions;
  1444. }
  1445. }
  1446. public uint MaskEffectivePermissions()
  1447. {
  1448. // used to propagate permissions restrictions outwards
  1449. // Modify does not propagate outwards.
  1450. uint mask=0x7fffffff;
  1451. foreach (TaskInventoryItem item in m_items.Values)
  1452. {
  1453. if(item.InvType == (sbyte)InventoryType.Landmark)
  1454. continue;
  1455. // apply current to normal permission bits
  1456. uint newperms = item.CurrentPermissions;
  1457. if ((newperms & (uint)PermissionMask.Copy) == 0)
  1458. mask &= ~(uint)PermissionMask.Copy;
  1459. if ((newperms & (uint)PermissionMask.Transfer) == 0)
  1460. mask &= ~(uint)PermissionMask.Transfer;
  1461. if ((newperms & (uint)PermissionMask.Export) == 0)
  1462. mask &= ~((uint)PermissionMask.Export);
  1463. // apply next owner restricted by current to folded bits
  1464. newperms &= item.NextPermissions;
  1465. if ((newperms & (uint)PermissionMask.Copy) == 0)
  1466. mask &= ~((uint)PermissionMask.FoldedCopy);
  1467. if ((newperms & (uint)PermissionMask.Transfer) == 0)
  1468. mask &= ~((uint)PermissionMask.FoldedTransfer);
  1469. if ((newperms & (uint)PermissionMask.Export) == 0)
  1470. mask &= ~((uint)PermissionMask.FoldedExport);
  1471. }
  1472. return mask;
  1473. }
  1474. public void ApplyNextOwnerPermissions()
  1475. {
  1476. foreach (TaskInventoryItem item in m_items.Values)
  1477. {
  1478. item.CurrentPermissions &= item.NextPermissions;
  1479. item.BasePermissions &= item.NextPermissions;
  1480. item.EveryonePermissions &= item.NextPermissions;
  1481. item.OwnerChanged = true;
  1482. item.PermsMask = 0;
  1483. item.PermsGranter = UUID.Zero;
  1484. }
  1485. }
  1486. public void ApplyGodPermissions(uint perms)
  1487. {
  1488. foreach (TaskInventoryItem item in m_items.Values)
  1489. {
  1490. item.CurrentPermissions = perms;
  1491. item.BasePermissions = perms;
  1492. }
  1493. m_inventorySerial++;
  1494. HasInventoryChanged = true;
  1495. }
  1496. /// <summary>
  1497. /// Returns true if this part inventory contains any scripts. False otherwise.
  1498. /// </summary>
  1499. /// <returns></returns>
  1500. public bool ContainsScripts()
  1501. {
  1502. m_items.LockItemsForRead(true);
  1503. bool res = (m_scripts != null && m_scripts.Count >0);
  1504. m_items.LockItemsForRead(false);
  1505. return res;
  1506. }
  1507. /// <summary>
  1508. /// Returns the count of scripts in this parts inventory.
  1509. /// </summary>
  1510. /// <returns></returns>
  1511. public int ScriptCount()
  1512. {
  1513. int count = 0;
  1514. m_items.LockItemsForRead(true);
  1515. if(m_scripts != null)
  1516. count = m_scripts.Count;
  1517. m_items.LockItemsForRead(false);
  1518. return count;
  1519. }
  1520. /// <summary>
  1521. /// Returns the count of running scripts in this parts inventory.
  1522. /// </summary>
  1523. /// <returns></returns>
  1524. public int RunningScriptCount()
  1525. {
  1526. IScriptModule[] scriptEngines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
  1527. if (scriptEngines.Length == 0)
  1528. return 0;
  1529. int count = 0;
  1530. m_items.LockItemsForRead(true);
  1531. if (m_scripts == null || m_scripts.Count == 0)
  1532. {
  1533. m_items.LockItemsForRead(false);
  1534. return 0;
  1535. }
  1536. List<TaskInventoryItem> scripts = new List<TaskInventoryItem>(m_scripts.Values);
  1537. m_items.LockItemsForRead(false);
  1538. foreach (TaskInventoryItem item in scripts)
  1539. {
  1540. foreach (IScriptModule engine in scriptEngines)
  1541. {
  1542. if (engine != null)
  1543. {
  1544. if (engine.HasScript(item.ItemID, out bool running))
  1545. {
  1546. if(running)
  1547. count++;
  1548. break;
  1549. }
  1550. }
  1551. }
  1552. }
  1553. return count;
  1554. }
  1555. public List<UUID> GetInventoryList()
  1556. {
  1557. m_items.LockItemsForRead(true);
  1558. List<UUID> ret = new List<UUID>(m_items.Count);
  1559. foreach (TaskInventoryItem item in m_items.Values)
  1560. ret.Add(item.ItemID);
  1561. m_items.LockItemsForRead(false);
  1562. return ret;
  1563. }
  1564. public List<TaskInventoryItem> GetInventoryItems()
  1565. {
  1566. m_items.LockItemsForRead(true);
  1567. List<TaskInventoryItem> ret = new List<TaskInventoryItem>(m_items.Values);
  1568. m_items.LockItemsForRead(false);
  1569. return ret;
  1570. }
  1571. public List<TaskInventoryItem> GetInventoryItems(InventoryType type)
  1572. {
  1573. m_items.LockItemsForRead(true);
  1574. List<TaskInventoryItem> ret = new List<TaskInventoryItem>(m_items.Count);
  1575. foreach (TaskInventoryItem item in m_items.Values)
  1576. if (item.InvType == (int)type)
  1577. ret.Add(item);
  1578. m_items.LockItemsForRead(false);
  1579. return ret;
  1580. }
  1581. public Dictionary<UUID, string> GetScriptStates()
  1582. {
  1583. return GetScriptStates(false);
  1584. }
  1585. public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
  1586. {
  1587. Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
  1588. if (m_part.ParentGroup.Scene == null) // Group not in a scene
  1589. return ret;
  1590. IScriptModule[] scriptEngines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
  1591. if (scriptEngines.Length == 0) // No engine at all
  1592. return ret;
  1593. m_items.LockItemsForRead(true);
  1594. if (m_scripts == null || m_scripts.Count == 0)
  1595. {
  1596. m_items.LockItemsForRead(false);
  1597. return ret;
  1598. }
  1599. List<TaskInventoryItem> scripts = new List<TaskInventoryItem>(m_scripts.Values);
  1600. m_items.LockItemsForRead(false);
  1601. foreach (TaskInventoryItem item in scripts)
  1602. {
  1603. foreach (IScriptModule e in scriptEngines)
  1604. {
  1605. if (e != null)
  1606. {
  1607. //m_log.DebugFormat(
  1608. // "[PRIM INVENTORY]: Getting script state from engine {0} for {1} in part {2} in group {3} in {4}",
  1609. // e.Name, item.Name, m_part.Name, m_part.ParentGroup.Name, m_part.ParentGroup.Scene.Name);
  1610. string n = e.GetXMLState(item.ItemID);
  1611. if (n != String.Empty)
  1612. {
  1613. if (oldIDs)
  1614. {
  1615. if (!ret.ContainsKey(item.OldItemID))
  1616. ret[item.OldItemID] = n;
  1617. }
  1618. else
  1619. {
  1620. if (!ret.ContainsKey(item.ItemID))
  1621. ret[item.ItemID] = n;
  1622. }
  1623. break;
  1624. }
  1625. }
  1626. }
  1627. }
  1628. return ret;
  1629. }
  1630. public void ResumeScripts()
  1631. {
  1632. IScriptModule[] scriptEngines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
  1633. if (scriptEngines.Length == 0)
  1634. return;
  1635. m_items.LockItemsForRead(true);
  1636. if (m_scripts == null || m_scripts.Count == 0)
  1637. {
  1638. m_items.LockItemsForRead(false);
  1639. return;
  1640. }
  1641. List<TaskInventoryItem> scripts = new List<TaskInventoryItem>(m_scripts.Values);
  1642. m_items.LockItemsForRead(false);
  1643. foreach (TaskInventoryItem item in scripts)
  1644. {
  1645. foreach (IScriptModule engine in scriptEngines)
  1646. {
  1647. if (engine != null)
  1648. {
  1649. //m_log.DebugFormat(
  1650. // "[PRIM INVENTORY]: Resuming script {0} {1} for {2}, OwnerChanged {3}",
  1651. // item.Name, item.ItemID, item.OwnerID, item.OwnerChanged);
  1652. if(!engine.ResumeScript(item.ItemID))
  1653. continue;
  1654. if (item.OwnerChanged)
  1655. engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
  1656. item.OwnerChanged = false;
  1657. }
  1658. }
  1659. }
  1660. }
  1661. }
  1662. }