Convert the agent asset transactions module to a new style module.

Refactor to remove the property "MyScene" and the pointless circular
refs to the managing classes. Converted the module to a non-shared module.
Reformatted source for 80 columns. Removed the special role the module
had in the old loader.
avinationmerge
Melanie 2010-12-04 04:33:14 +01:00
parent 8e3bacc691
commit da91a2ab7e
4 changed files with 161 additions and 173 deletions

View File

@ -106,8 +106,8 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
m_openSim.ModuleLoader.LoadDefaultSharedModule(new LoadImageURLModule());
m_log.Info("[LOADREGIONSPLUGIN]: XMLRPCModule...");
m_openSim.ModuleLoader.LoadDefaultSharedModule(new XMLRPCModule());
m_log.Info("[LOADREGIONSPLUGIN]: AssetTransactionModule...");
m_openSim.ModuleLoader.LoadDefaultSharedModule(new AssetTransactionModule());
// m_log.Info("[LOADREGIONSPLUGIN]: AssetTransactionModule...");
// m_openSim.ModuleLoader.LoadDefaultSharedModule(new AssetTransactionModule());
m_log.Info("[LOADREGIONSPLUGIN]: Done.");
if (!CheckRegionsForSanity(regionsToLoad))

View File

@ -41,19 +41,22 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
/// </summary>
public class AgentAssetTransactions
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog m_log = LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
// Fields
private bool m_dumpAssetsToFile;
public AssetTransactionModule Manager;
private Scene m_Scene;
public UUID UserID;
public Dictionary<UUID, AssetXferUploader> XferUploaders = new Dictionary<UUID, AssetXferUploader>();
public Dictionary<UUID, AssetXferUploader> XferUploaders =
new Dictionary<UUID, AssetXferUploader>();
// Methods
public AgentAssetTransactions(UUID agentID, AssetTransactionModule manager, bool dumpAssetsToFile)
public AgentAssetTransactions(UUID agentID, Scene scene,
bool dumpAssetsToFile)
{
m_Scene = scene;
UserID = agentID;
Manager = manager;
m_dumpAssetsToFile = dumpAssetsToFile;
}
@ -61,7 +64,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
{
if (!XferUploaders.ContainsKey(transactionID))
{
AssetXferUploader uploader = new AssetXferUploader(this, m_dumpAssetsToFile);
AssetXferUploader uploader = new AssetXferUploader(m_Scene,
m_dumpAssetsToFile);
lock (XferUploaders)
{
@ -88,22 +92,25 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
}
}
public void RequestCreateInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID,
uint callbackID, string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask)
public void RequestCreateInventoryItem(IClientAPI remoteClient,
UUID transactionID, UUID folderID, uint callbackID,
string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask)
{
if (XferUploaders.ContainsKey(transactionID))
{
XferUploaders[transactionID].RequestCreateInventoryItem(remoteClient, transactionID, folderID,
callbackID, description, name, invType, type,
wearableType, nextOwnerMask);
XferUploaders[transactionID].RequestCreateInventoryItem(
remoteClient, transactionID, folderID,
callbackID, description, name, invType, type,
wearableType, nextOwnerMask);
}
}
/// <summary>
/// Get an uploaded asset. If the data is successfully retrieved, the transaction will be removed.
/// Get an uploaded asset. If the data is successfully retrieved,
/// the transaction will be removed.
/// </summary>
/// <param name="transactionID"></param>
/// <returns>The asset if the upload has completed, null if it has not.</returns>
@ -125,48 +132,21 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
return null;
}
//private void CreateItemFromUpload(AssetBase asset, IClientAPI ourClient, UUID inventoryFolderID, uint nextPerms, uint wearableType)
//{
// Manager.MyScene.CommsManager.AssetCache.AddAsset(asset);
// CachedUserInfo userInfo = Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails(
// ourClient.AgentId);
// if (userInfo != null)
// {
// InventoryItemBase item = new InventoryItemBase();
// item.Owner = ourClient.AgentId;
// item.Creator = ourClient.AgentId;
// item.ID = UUID.Random();
// item.AssetID = asset.FullID;
// item.Description = asset.Description;
// item.Name = asset.Name;
// item.AssetType = asset.Type;
// item.InvType = asset.Type;
// item.Folder = inventoryFolderID;
// item.BasePermissions = 0x7fffffff;
// item.CurrentPermissions = 0x7fffffff;
// item.EveryOnePermissions = 0;
// item.NextPermissions = nextPerms;
// item.Flags = wearableType;
// item.CreationDate = Util.UnixTimeSinceEpoch();
// userInfo.AddItem(item);
// ourClient.SendInventoryItemCreateUpdate(item);
// }
// else
// {
// m_log.ErrorFormat(
// "[ASSET TRANSACTIONS]: Could not find user {0} for inventory item creation",
// ourClient.AgentId);
// }
//}
public void RequestUpdateTaskInventoryItem(
IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item)
public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient,
SceneObjectPart part, UUID transactionID,
TaskInventoryItem item)
{
if (XferUploaders.ContainsKey(transactionID))
{
AssetBase asset = XferUploaders[transactionID].GetAssetData();
AssetBase asset = GetTransactionAsset(transactionID);
// Only legacy viewers use this, and they prefer CAPS, which
// we have, so this really never runs.
// Allow it, but only for "safe" types.
if ((InventoryType)item.InvType != InventoryType.Notecard &&
(InventoryType)item.InvType != InventoryType.LSL)
return;
if (asset != null)
{
m_log.DebugFormat(
@ -178,32 +158,23 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
asset.Type = (sbyte)item.Type;
item.AssetID = asset.FullID;
Manager.MyScene.AssetService.Store(asset);
m_Scene.AssetService.Store(asset);
if (part.Inventory.UpdateInventoryItem(item))
{
if ((InventoryType)item.InvType == InventoryType.Notecard)
remoteClient.SendAgentAlertMessage("Notecard saved", false);
else if ((InventoryType)item.InvType == InventoryType.LSL)
remoteClient.SendAgentAlertMessage("Script saved", false);
else
remoteClient.SendAgentAlertMessage("Item saved", false);
part.GetProperties(remoteClient);
}
part.Inventory.UpdateInventoryItem(item);
}
}
}
public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID,
InventoryItemBase item)
public void RequestUpdateInventoryItem(IClientAPI remoteClient,
UUID transactionID, InventoryItemBase item)
{
if (XferUploaders.ContainsKey(transactionID))
if (XferUploaders.ContainsKey(transactionID))
{
UUID assetID = UUID.Combine(transactionID, remoteClient.SecureSessionId);
UUID assetID = UUID.Combine(transactionID,
remoteClient.SecureSessionId);
AssetBase asset = Manager.MyScene.AssetService.Get(assetID.ToString());
AssetBase asset = m_Scene.AssetService.Get(
assetID.ToString());
if (asset == null)
{
@ -219,10 +190,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
asset.Type = (sbyte)item.AssetType;
item.AssetID = asset.FullID;
Manager.MyScene.AssetService.Store(asset);
m_Scene.AssetService.Store(asset);
}
IInventoryService invService = Manager.MyScene.InventoryService;
IInventoryService invService = m_Scene.InventoryService;
invService.UpdateItem(item);
}
}

View File

@ -34,22 +34,19 @@ using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using Mono.Addins;
namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
{
public class AssetTransactionModule : IRegionModule, IAgentAssetTransactions
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AssetTransactionModule")]
public class AssetTransactionModule : INonSharedRegionModule,
IAgentAssetTransactions
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// private static readonly ILog m_log = LogManager.GetLogger(
// MethodBase.GetCurrentMethod().DeclaringType);
private readonly Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
protected Scene m_Scene;
private bool m_dumpAssetsToFile = false;
private Scene m_scene = null;
[Obsolete]
public Scene MyScene
{
get{ return m_scene;}
}
/// <summary>
/// Each agent has its own singleton collection of transactions
@ -57,33 +54,24 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
private Dictionary<UUID, AgentAssetTransactions> AgentTransactions =
new Dictionary<UUID, AgentAssetTransactions>();
public AssetTransactionModule()
{
//m_log.Debug("creating AgentAssetTransactionModule");
}
#region IRegionModule Members
public void Initialise(Scene scene, IConfigSource config)
public void Initialise(IConfigSource config)
{
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
{
// m_log.Debug("initialising AgentAssetTransactionModule");
RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
scene.RegisterModuleInterface<IAgentAssetTransactions>(this);
scene.EventManager.OnNewClient += NewClient;
}
// EVIL HACK!
// This needs killing!
//
if (m_scene == null)
m_scene = scene;
}
public void PostInitialise()
public void AddRegion(Scene scene)
{
m_Scene = scene;
scene.RegisterModuleInterface<IAgentAssetTransactions>(this);
scene.EventManager.OnNewClient += NewClient;
}
public void RegionLoaded(Scene scene)
{
}
public void RemoveRegion(Scene scene)
{
}
@ -96,9 +84,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
get { return "AgentTransactionModule"; }
}
public bool IsSharedModule
public Type ReplaceableInterface
{
get { return true; }
get { return typeof(IAgentAssetTransactions); }
}
#endregion
@ -111,8 +99,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
#region AgentAssetTransactions
/// <summary>
/// Get the collection of asset transactions for the given user. If one does not already exist, it
/// is created.
/// Get the collection of asset transactions for the given user.
/// If one does not already exist, it is created.
/// </summary>
/// <param name="userID"></param>
/// <returns></returns>
@ -122,7 +110,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
{
if (!AgentTransactions.ContainsKey(userID))
{
AgentAssetTransactions transactions = new AgentAssetTransactions(userID, this, m_dumpAssetsToFile);
AgentAssetTransactions transactions =
new AgentAssetTransactions(userID, m_Scene,
m_dumpAssetsToFile);
AgentTransactions.Add(userID, transactions);
}
@ -131,8 +122,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
}
/// <summary>
/// Remove the given agent asset transactions. This should be called when a client is departing
/// from a scene (and hence won't be making any more transactions here).
/// Remove the given agent asset transactions. This should be called
/// when a client is departing from a scene (and hence won't be making
/// any more transactions here).
/// </summary>
/// <param name="userID"></param>
public void RemoveAgentAssetTransactions(UUID userID)
@ -146,10 +138,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
}
/// <summary>
/// Create an inventory item from data that has been received through a transaction.
///
/// This is called when new clothing or body parts are created. It may also be called in other
/// situations.
/// Create an inventory item from data that has been received through
/// a transaction.
/// This is called when new clothing or body parts are created.
/// It may also be called in other situations.
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="transactionID"></param>
@ -161,61 +153,72 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
/// <param name="type"></param>
/// <param name="wearableType"></param>
/// <param name="nextOwnerMask"></param>
public void HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID,
uint callbackID, string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask)
public void HandleItemCreationFromTransaction(IClientAPI remoteClient,
UUID transactionID, UUID folderID, uint callbackID,
string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask)
{
// m_log.DebugFormat(
// "[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name);
// m_log.DebugFormat(
// "[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name);
AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
AgentAssetTransactions transactions =
GetUserTransactions(remoteClient.AgentId);
transactions.RequestCreateInventoryItem(
remoteClient, transactionID, folderID, callbackID, description,
name, invType, type, wearableType, nextOwnerMask);
transactions.RequestCreateInventoryItem(remoteClient, transactionID,
folderID, callbackID, description, name, invType, type,
wearableType, nextOwnerMask);
}
/// <summary>
/// Update an inventory item with data that has been received through a transaction.
/// Update an inventory item with data that has been received through a
/// transaction.
///
/// This is called when clothing or body parts are updated (for instance, with new textures or
/// colours). It may also be called in other situations.
/// This is called when clothing or body parts are updated (for
/// instance, with new textures or colours). It may also be called in
/// other situations.
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="transactionID"></param>
/// <param name="item"></param>
public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID,
InventoryItemBase item)
public void HandleItemUpdateFromTransaction(IClientAPI remoteClient,
UUID transactionID, InventoryItemBase item)
{
// m_log.DebugFormat(
// "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}",
// item.Name);
// m_log.DebugFormat(
// "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}",
// item.Name);
AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
AgentAssetTransactions transactions =
GetUserTransactions(remoteClient.AgentId);
transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item);
transactions.RequestUpdateInventoryItem(remoteClient,
transactionID, item);
}
/// <summary>
/// Update a task inventory item with data that has been received through a transaction.
/// Update a task inventory item with data that has been received
/// through a transaction.
///
/// This is currently called when, for instance, a notecard in a prim is saved. The data is sent
/// up through a single AssetUploadRequest. A subsequent UpdateTaskInventory then references the transaction
/// This is currently called when, for instance, a notecard in a prim
/// is saved. The data is sent up through a single AssetUploadRequest.
/// A subsequent UpdateTaskInventory then references the transaction
/// and comes through this method.
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="transactionID"></param>
/// <param name="item"></param>
public void HandleTaskItemUpdateFromTransaction(
IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item)
public void HandleTaskItemUpdateFromTransaction(IClientAPI remoteClient,
SceneObjectPart part, UUID transactionID,
TaskInventoryItem item)
{
// m_log.DebugFormat(
// "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0}",
// item.Name);
// m_log.DebugFormat(
// "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0}",
// item.Name);
AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
AgentAssetTransactions transactions =
GetUserTransactions(remoteClient.AgentId);
transactions.RequestUpdateTaskInventoryItem(remoteClient, part, transactionID, item);
transactions.RequestUpdateTaskInventoryItem(remoteClient, part,
transactionID, item);
}
/// <summary>
@ -227,8 +230,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
/// <param name="type"></param>
/// <param name="data"></param></param>
/// <param name="tempFile"></param>
public void HandleUDPUploadRequest(IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type,
byte[] data, bool storeLocal, bool tempFile)
public void HandleUDPUploadRequest(IClientAPI remoteClient,
UUID assetID, UUID transaction, sbyte type, byte[] data,
bool storeLocal, bool tempFile)
{
// m_log.Debug("HandleUDPUploadRequest - assetID: " + assetID.ToString() + " transaction: " + transaction.ToString() + " type: " + type.ToString() + " storelocal: " + storeLocal + " tempFile: " + tempFile);
@ -251,27 +255,33 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
}
}
AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
AgentAssetTransactions transactions =
GetUserTransactions(remoteClient.AgentId);
AssetXferUploader uploader =
transactions.RequestXferUploader(transaction);
AssetXferUploader uploader = transactions.RequestXferUploader(transaction);
if (uploader != null)
{
uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal, tempFile);
uploader.Initialise(remoteClient, assetID, transaction, type,
data, storeLocal, tempFile);
}
}
/// <summary>
/// Handle asset transfer data packets received in response to the asset upload request in
/// HandleUDPUploadRequest()
/// Handle asset transfer data packets received in response to the
/// asset upload request in HandleUDPUploadRequest()
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="xferID"></param>
/// <param name="packetID"></param>
/// <param name="data"></param>
public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data)
public void HandleXfer(IClientAPI remoteClient, ulong xferID,
uint packetID, byte[] data)
{
//m_log.Debug("xferID: " + xferID + " packetID: " + packetID + " data!");
AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
AgentAssetTransactions transactions =
GetUserTransactions(remoteClient.AgentId);
transactions.HandleXfer(xferID, packetID, data);
}

View File

@ -31,7 +31,7 @@ using System.Reflection;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
@ -50,17 +50,17 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
private bool m_finished = false;
private string m_name = String.Empty;
private bool m_storeLocal;
private AgentAssetTransactions m_userTransactions;
private uint nextPerm = 0;
private IClientAPI ourClient;
private UUID TransactionID = UUID.Zero;
private sbyte type = 0;
private byte wearableType = 0;
public ulong XferID;
private Scene m_Scene;
public AssetXferUploader(AgentAssetTransactions transactions, bool dumpAssetToFile)
public AssetXferUploader(Scene scene, bool dumpAssetToFile)
{
m_userTransactions = transactions;
m_Scene = scene;
m_dumpAssetToFile = dumpAssetToFile;
}
@ -108,11 +108,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
/// <param name="packetID"></param>
/// <param name="data"></param>
/// <returns>True if the transfer is complete, false otherwise</returns>
public bool Initialise(IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data,
bool storeLocal, bool tempFile)
public bool Initialise(IClientAPI remoteClient, UUID assetID,
UUID transaction, sbyte type, byte[] data, bool storeLocal,
bool tempFile)
{
ourClient = remoteClient;
m_asset = new AssetBase(assetID, "blank", type, remoteClient.AgentId.ToString());
m_asset = new AssetBase(assetID, "blank", type,
remoteClient.AgentId.ToString());
m_asset.Data = data;
m_asset.Description = "empty";
m_asset.Local = storeLocal;
@ -137,12 +139,14 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
protected void RequestStartXfer()
{
XferID = Util.GetNextXferID();
ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID, 0, new byte[0]);
ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID,
0, new byte[0]);
}
protected void SendCompleteMessage()
{
ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID);
ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true,
m_asset.FullID);
m_finished = true;
if (m_createItem)
@ -151,18 +155,20 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
}
else if (m_storeLocal)
{
m_userTransactions.Manager.MyScene.AssetService.Store(m_asset);
m_Scene.AssetService.Store(m_asset);
}
m_log.DebugFormat(
"[ASSET TRANSACTIONS]: Uploaded asset {0} for transaction {1}", m_asset.FullID, TransactionID);
"[ASSET TRANSACTIONS]: Uploaded asset {0} for transaction {1}",
m_asset.FullID, TransactionID);
if (m_dumpAssetToFile)
{
DateTime now = DateTime.Now;
string filename =
String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", now.Year, now.Month, now.Day,
now.Hour, now.Minute, now.Second, m_asset.Name, m_asset.Type);
String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat",
now.Year, now.Month, now.Day, now.Hour, now.Minute,
now.Second, m_asset.Name, m_asset.Type);
SaveAssetToFile(filename, m_asset.Data);
}
}
@ -181,9 +187,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
fs.Close();
}
public void RequestCreateInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID,
uint callbackID, string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask)
public void RequestCreateInventoryItem(IClientAPI remoteClient,
UUID transactionID, UUID folderID, uint callbackID,
string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask)
{
if (TransactionID == transactionID)
{
@ -212,7 +219,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
private void DoCreateItem(uint callbackID)
{
m_userTransactions.Manager.MyScene.AssetService.Store(m_asset);
m_Scene.AssetService.Store(m_asset);
InventoryItemBase item = new InventoryItemBase();
item.Owner = ourClient.AgentId;
@ -232,7 +239,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
item.Flags = (uint) wearableType;
item.CreationDate = Util.UnixTimeSinceEpoch();
if (m_userTransactions.Manager.MyScene.AddInventoryItem(item))
if (m_Scene.AddInventoryItem(item))
ourClient.SendInventoryItemCreateUpdate(item, callbackID);
else
ourClient.SendAlertMessage("Unable to create inventory item");