/// <summary> /// Convert raw uploaded data into the appropriate asset and item. /// </summary> /// <param name="assetID"></param> /// <param name="inventoryItem"></param> /// <param name="data"></param> public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, string assetType, int cost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances, bool IsAtestUpload, ref string error, ref int nextOwnerMask, ref int groupMask, ref int everyoneMask) { lock (m_ModelCost) m_FileAgentInventoryState = FileAgentInventoryState.processUpload; m_log.DebugFormat( "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}", assetID, inventoryItem, inventoryType, assetType); sbyte assType = 0; sbyte inType = 0; IClientAPI client = null; UUID owner_id = m_HostCapsObj.AgentID; UUID creatorID; bool istest = IsAtestUpload && m_enableFreeTestUpload && (cost > 0); bool restrictPerms = m_RestrictFreeTestUploadPerms && istest; if (istest && m_testAssetsCreatorID != UUID.Zero) creatorID = m_testAssetsCreatorID; else creatorID = owner_id; string creatorIDstr = creatorID.ToString(); IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>(); if (mm != null) { // make sure client still has enougth credit if (!mm.UploadCovered(m_HostCapsObj.AgentID, (int)cost)) { error = "Insufficient funds."; return; } } // strings to types if (inventoryType == "sound") { inType = (sbyte)InventoryType.Sound; assType = (sbyte)AssetType.Sound; } else if (inventoryType == "snapshot") { inType = (sbyte)InventoryType.Snapshot; } else if (inventoryType == "animation") { inType = (sbyte)InventoryType.Animation; assType = (sbyte)AssetType.Animation; } else if (inventoryType == "animset") { inType = (sbyte)CustomInventoryType.AnimationSet; assType = (sbyte)CustomAssetType.AnimationSet; m_log.Debug("got animset upload request"); } else if (inventoryType == "wearable") { inType = (sbyte)InventoryType.Wearable; switch (assetType) { case "bodypart": assType = (sbyte)AssetType.Bodypart; break; case "clothing": assType = (sbyte)AssetType.Clothing; break; } } else if (inventoryType == "object") { if (assetType == "mesh") // this code for now is for mesh models uploads only { inType = (sbyte)InventoryType.Object; assType = (sbyte)AssetType.Object; List<Vector3> positions = new List<Vector3>(); List<Quaternion> rotations = new List<Quaternion>(); OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data); // compare and get updated information /* does nothing still we do need something to avoid special viewer to upload something diferent from the cost estimation bool mismatchError = true; while (mismatchError) { mismatchError = false; } if (mismatchError) { error = "Upload and fee estimation information don't match"; lock (m_ModelCost) m_FileAgentInventoryState = FileAgentInventoryState.idle; return; } */ OSDArray instance_list = (OSDArray)request["instance_list"]; OSDArray mesh_list = (OSDArray)request["mesh_list"]; OSDArray texture_list = (OSDArray)request["texture_list"]; SceneObjectGroup grp = null; // create and store texture assets bool doTextInv = (!istest && m_enableModelUploadTextureToInventory && texturesFolder != UUID.Zero); List<UUID> textures = new List<UUID>(); // if (doTextInv) m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client); if(client == null) // don't put textures in inventory if there is no client doTextInv = false; for (int i = 0; i < texture_list.Count; i++) { AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, creatorIDstr); textureAsset.Data = texture_list[i].AsBinary(); if (istest) textureAsset.Local = true; m_assetService.Store(textureAsset); textures.Add(textureAsset.FullID); if (doTextInv) { string name = assetName; if (name.Length > 25) name = name.Substring(0, 24); name += "_Texture#" + i.ToString(); InventoryItemBase texitem = new InventoryItemBase(); texitem.Owner = m_HostCapsObj.AgentID; texitem.CreatorId = creatorIDstr; texitem.CreatorData = String.Empty; texitem.ID = UUID.Random(); texitem.AssetID = textureAsset.FullID; texitem.Description = "mesh model texture"; texitem.Name = name; texitem.AssetType = (int)AssetType.Texture; texitem.InvType = (int)InventoryType.Texture; texitem.Folder = texturesFolder; texitem.CurrentPermissions = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Export); texitem.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export; texitem.EveryOnePermissions = 0; texitem.NextPermissions = (uint)PermissionMask.All; texitem.CreationDate = Util.UnixTimeSinceEpoch(); m_Scene.AddInventoryItem(client, texitem); texitem = null; } } // create and store meshs assets List<UUID> meshAssets = new List<UUID>(); List<bool> meshAvatarSkeletons = new List<bool>(); List<bool> meshAvatarColliders = new List<bool>(); bool curAvSkeleton; bool curAvCollider; for (int i = 0; i < mesh_list.Count; i++) { curAvSkeleton = false; curAvCollider = false; // we do need to parse the mesh now OSD osd = OSDParser.DeserializeLLSDBinary(mesh_list[i]); if (osd is OSDMap) { OSDMap mosd = (OSDMap)osd; if (mosd.ContainsKey("skeleton")) { OSDMap skeleton = (OSDMap)mosd["skeleton"]; int sksize = skeleton["size"].AsInteger(); if (sksize > 0) curAvSkeleton = true; } } AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, creatorIDstr); meshAsset.Data = mesh_list[i].AsBinary(); if (istest) meshAsset.Local = true; m_assetService.Store(meshAsset); meshAssets.Add(meshAsset.FullID); meshAvatarSkeletons.Add(curAvSkeleton); meshAvatarColliders.Add(curAvCollider); // test code if (curAvSkeleton && client != null) { string name = assetName; if (name.Length > 25) name = name.Substring(0, 24); name += "_Mesh#" + i.ToString(); InventoryItemBase meshitem = new InventoryItemBase(); meshitem.Owner = m_HostCapsObj.AgentID; meshitem.CreatorId = creatorIDstr; meshitem.CreatorData = String.Empty; meshitem.ID = UUID.Random(); meshitem.AssetID = meshAsset.FullID; meshitem.Description = "mesh "; meshitem.Name = name; meshitem.AssetType = (int)AssetType.Mesh; meshitem.InvType = (int)InventoryType.Mesh; // meshitem.Folder = UUID.Zero; // send to default meshitem.Folder = parentFolder; // dont let it go to folder Meshes that viewers dont show // If we set PermissionMask.All then when we rez the item the next permissions will replace the current // (owner) permissions. This becomes a problem if next permissions are changed. meshitem.CurrentPermissions = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); meshitem.BasePermissions = (uint)PermissionMask.All; meshitem.EveryOnePermissions = 0; meshitem.NextPermissions = (uint)PermissionMask.All; meshitem.CreationDate = Util.UnixTimeSinceEpoch(); m_Scene.AddInventoryItem(client, meshitem); meshitem = null; } } int skipedMeshs = 0; // build prims from instances for (int i = 0; i < instance_list.Count; i++) { OSDMap inner_instance_list = (OSDMap)instance_list[i]; // skip prims that are 2 small Vector3 scale = inner_instance_list["scale"].AsVector3(); if (scale.X < m_PrimScaleMin || scale.Y < m_PrimScaleMin || scale.Z < m_PrimScaleMin) { skipedMeshs++; continue; } PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); Primitive.TextureEntry textureEntry = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE); OSDArray face_list = (OSDArray)inner_instance_list["face_list"]; for (uint face = 0; face < face_list.Count; face++) { OSDMap faceMap = (OSDMap)face_list[(int)face]; Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face); if (faceMap.ContainsKey("fullbright")) f.Fullbright = faceMap["fullbright"].AsBoolean(); if (faceMap.ContainsKey("diffuse_color")) f.RGBA = faceMap["diffuse_color"].AsColor4(); int textureNum = faceMap["image"].AsInteger(); float imagerot = faceMap["imagerot"].AsInteger(); float offsets = (float)faceMap["offsets"].AsReal(); float offsett = (float)faceMap["offsett"].AsReal(); float scales = (float)faceMap["scales"].AsReal(); float scalet = (float)faceMap["scalet"].AsReal(); if (imagerot != 0) f.Rotation = imagerot; if (offsets != 0) f.OffsetU = offsets; if (offsett != 0) f.OffsetV = offsett; if (scales != 0) f.RepeatU = scales; if (scalet != 0) f.RepeatV = scalet; if (textures.Count > textureNum) f.TextureID = textures[textureNum]; else f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE; textureEntry.FaceTextures[face] = f; } pbs.TextureEntry = textureEntry.GetBytes(); bool hasmesh = false; if (inner_instance_list.ContainsKey("mesh")) // seems to happen always but ... { int meshindx = inner_instance_list["mesh"].AsInteger(); if (meshAssets.Count > meshindx) { pbs.SculptEntry = true; pbs.SculptType = (byte)SculptType.Mesh; pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction // data will be requested from asset on rez (i hope) hasmesh = true; } } Vector3 position = inner_instance_list["position"].AsVector3(); Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); // for now viwers do send fixed defaults // but this may change // int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger(); byte physicsShapeType = (byte)PhysShapeType.convex; // default is simple convex // int material = inner_instance_list["material"].AsInteger(); byte material = (byte)Material.Wood; // no longer used - begin ------------------------ // int mesh = inner_instance_list["mesh"].AsInteger(); // OSDMap permissions = (OSDMap)inner_instance_list["permissions"]; // int base_mask = permissions["base_mask"].AsInteger(); // int everyone_mask = permissions["everyone_mask"].AsInteger(); // UUID creator_id = permissions["creator_id"].AsUUID(); // UUID group_id = permissions["group_id"].AsUUID(); // int group_mask = permissions["group_mask"].AsInteger(); // bool is_owner_group = permissions["is_owner_group"].AsBoolean(); // UUID last_owner_id = permissions["last_owner_id"].AsUUID(); // int next_owner_mask = permissions["next_owner_mask"].AsInteger(); // UUID owner_id = permissions["owner_id"].AsUUID(); // int owner_mask = permissions["owner_mask"].AsInteger(); // no longer used - end ------------------------ SceneObjectPart prim = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); prim.Scale = scale; rotations.Add(rotation); positions.Add(position); prim.UUID = UUID.Random(); prim.CreatorID = creatorID; prim.OwnerID = owner_id; prim.GroupID = UUID.Zero; prim.LastOwnerID = creatorID; prim.CreationDate = Util.UnixTimeSinceEpoch(); if (grp == null) prim.Name = assetName; else prim.Name = assetName + "#" + i.ToString(); prim.EveryoneMask = 0; prim.GroupMask = 0; if (restrictPerms) { prim.BaseMask = (uint)(PermissionMask.Move | PermissionMask.Modify); prim.OwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify); prim.NextOwnerMask = 0; } else { prim.BaseMask = (uint)PermissionMask.All | (uint)PermissionMask.Export; prim.OwnerMask = (uint)PermissionMask.All | (uint)PermissionMask.Export; prim.GroupMask = prim.BaseMask & (uint)groupMask; prim.EveryoneMask = prim.BaseMask & (uint)everyoneMask; prim.NextOwnerMask = prim.BaseMask & (uint)nextOwnerMask; // If the viewer gives us bogus permissions, revert to the SL // default of transfer only. if ((prim.NextOwnerMask & (uint)PermissionMask.All) == 0) prim.NextOwnerMask = (uint)PermissionMask.Transfer; } if(istest) prim.Description = "For testing only. Other uses are prohibited"; else prim.Description = ""; prim.Material = material; prim.PhysicsShapeType = physicsShapeType; // prim.BaseMask = (uint)base_mask; // prim.EveryoneMask = (uint)everyone_mask; // prim.GroupMask = (uint)group_mask; // prim.NextOwnerMask = (uint)next_owner_mask; // prim.OwnerMask = (uint)owner_mask; if (grp == null) { grp = new SceneObjectGroup(prim); grp.LastOwnerID = creatorID; } else grp.AddPart(prim); } Vector3 rootPos = positions[0]; if (grp.Parts.Length > 1) { // Fix first link number grp.RootPart.LinkNum++; Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]); Quaternion tmprot; Vector3 offset; // fix children rotations and positions for (int i = 1; i < rotations.Count; i++) { tmprot = rotations[i]; tmprot = rootRotConj * tmprot; grp.Parts[i].RotationOffset = tmprot; offset = positions[i] - rootPos; offset *= rootRotConj; grp.Parts[i].OffsetPosition = offset; } grp.AbsolutePosition = rootPos; grp.UpdateGroupRotationR(rotations[0]); } else { grp.AbsolutePosition = rootPos; grp.UpdateGroupRotationR(rotations[0]); } data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp)); } else // not a mesh model { m_log.ErrorFormat("[CAPS Asset Upload] got unsuported assetType for object upload"); return; } } AssetBase asset; asset = new AssetBase(assetID, assetName, assType, creatorIDstr); asset.Data = data; if (istest) asset.Local = true; if (AddNewAsset != null) AddNewAsset(asset); else if (m_assetService != null) m_assetService.Store(asset); InventoryItemBase item = new InventoryItemBase(); item.Owner = m_HostCapsObj.AgentID; item.CreatorId = creatorIDstr; item.CreatorData = String.Empty; item.ID = inventoryItem; item.AssetID = asset.FullID; if (istest) { item.Description = "For testing only. Other uses are prohibited"; item.Flags = (uint) (InventoryItemFlags.SharedSingleReference); } else item.Description = assetDescription; item.Name = assetName; item.AssetType = assType; item.InvType = inType; item.Folder = parentFolder; // If we set PermissionMask.All then when we rez the item the next permissions will replace the current // (owner) permissions. This becomes a problem if next permissions are changed. if (inType == (sbyte)CustomInventoryType.AnimationSet) { AnimationSet.setCreateItemPermitions(item); } else if (restrictPerms) { item.BasePermissions = (uint)(PermissionMask.Move | PermissionMask.Modify); item.CurrentPermissions = (uint)(PermissionMask.Move | PermissionMask.Modify); item.GroupPermissions = 0; item.EveryOnePermissions = 0; item.NextPermissions = 0; } else { item.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export; item.CurrentPermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export; item.GroupPermissions = item.BasePermissions & (uint)groupMask; item.EveryOnePermissions = item.BasePermissions & (uint)everyoneMask; item.NextPermissions = item.BasePermissions & (uint)nextOwnerMask; if ((item.NextPermissions & (uint)PermissionMask.All) == 0) item.NextPermissions = (uint)PermissionMask.Transfer; } item.CreationDate = Util.UnixTimeSinceEpoch(); everyoneMask = (int)item.EveryOnePermissions; groupMask = (int)item.GroupPermissions; nextOwnerMask = (int)item.NextPermissions; m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client); if (AddNewInventoryItem != null) { if (istest) { m_Scene.AddInventoryItem(client, item); /* AddNewInventoryItem(m_HostCapsObj.AgentID, item, 0); if (client != null) client.SendAgentAlertMessage("Upload will have no cost, for personal test purposes only. Other uses are forbiden. Items may not work on a another region" , true); */ } else { AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost); // if (client != null) // { // // let users see anything.. i don't so far // string str; // if (cost > 0) // // dont remember where is money unit name to put here // str = "Upload complete. charged " + cost.ToString() + "$"; // else // str = "Upload complete"; // client.SendAgentAlertMessage(str, true); // } } } lock (m_ModelCost) m_FileAgentInventoryState = FileAgentInventoryState.idle; }
public BunchOfCaps(Scene scene, Caps caps) { m_Scene = scene; m_HostCapsObj = caps; // create a model upload cost provider m_ModelCost = new ModelCost(); // tell it about scene object limits m_ModelCost.NonPhysicalPrimScaleMax = m_Scene.m_maxNonphys; m_ModelCost.PhysicalPrimScaleMax = m_Scene.m_maxPhys; m_ModelCost.ObjectLinkedPartsMax = m_Scene.m_linksetCapacity; // m_ModelCost.ObjectLinkedPartsMax = ?? // m_ModelCost.PrimScaleMin = ?? m_PrimScaleMin = m_ModelCost.PrimScaleMin; float modelTextureUploadFactor = m_ModelCost.ModelTextureCostFactor; float modelUploadFactor = m_ModelCost.ModelMeshCostFactor; float modelMinUploadCostFactor = m_ModelCost.ModelMinCostFactor; float modelPrimCreationCost = m_ModelCost.primCreationCost; float modelMeshByteCost = m_ModelCost.bytecost; IConfigSource config = m_Scene.Config; if (config != null) { IConfig sconfig = config.Configs["Startup"]; if (sconfig != null) { m_levelUpload = sconfig.GetInt("LevelUpload", 0); } IConfig appearanceConfig = config.Configs["Appearance"]; if (appearanceConfig != null) { m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); } // economy for model upload IConfig EconomyConfig = config.Configs["Economy"]; if (EconomyConfig != null) { modelUploadFactor = EconomyConfig.GetFloat("MeshModelUploadCostFactor", modelUploadFactor); modelTextureUploadFactor = EconomyConfig.GetFloat("MeshModelUploadTextureCostFactor", modelTextureUploadFactor); modelMinUploadCostFactor = EconomyConfig.GetFloat("MeshModelMinCostFactor", modelMinUploadCostFactor); // next 2 are normalized so final cost is afected by modelUploadFactor above and normal cost modelPrimCreationCost = EconomyConfig.GetFloat("ModelPrimCreationCost", modelPrimCreationCost); modelMeshByteCost = EconomyConfig.GetFloat("ModelMeshByteCost", modelMeshByteCost); m_enableModelUploadTextureToInventory = EconomyConfig.GetBoolean("MeshModelAllowTextureToInventory", m_enableModelUploadTextureToInventory); m_RestrictFreeTestUploadPerms = EconomyConfig.GetBoolean("m_RestrictFreeTestUploadPerms", m_RestrictFreeTestUploadPerms); m_enableFreeTestUpload = EconomyConfig.GetBoolean("AllowFreeTestUpload", m_enableFreeTestUpload); m_ForceFreeTestUpload = EconomyConfig.GetBoolean("ForceFreeTestUpload", m_ForceFreeTestUpload); string testcreator = EconomyConfig.GetString("TestAssetsCreatorID", ""); if (testcreator != "") { UUID id; UUID.TryParse(testcreator, out id); if (id != null) m_testAssetsCreatorID = id; } m_ModelCost.ModelMeshCostFactor = modelUploadFactor; m_ModelCost.ModelTextureCostFactor = modelTextureUploadFactor; m_ModelCost.ModelMinCostFactor = modelMinUploadCostFactor; m_ModelCost.primCreationCost = modelPrimCreationCost; m_ModelCost.bytecost = modelMeshByteCost; } } m_assetService = m_Scene.AssetService; m_regionName = m_Scene.RegionInfo.RegionName; RegisterHandlers(); AddNewInventoryItem = m_Scene.AddUploadedInventoryItem; ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset; TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset; GetClient = m_Scene.SceneGraph.GetControllingClient; m_FileAgentInventoryState = FileAgentInventoryState.idle; }
/// <summary> /// /// </summary> /// <param name="llsdRequest"></param> /// <returns></returns> public LLSDAssetUploadResponse NewAgentInventoryRequest(LLSDAssetUploadRequest llsdRequest) { //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString()); //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type); // start by getting the client IClientAPI client = null; m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client); // check current state so we only have one service at a time lock (m_ModelCost) { switch (m_FileAgentInventoryState) { case FileAgentInventoryState.processRequest: case FileAgentInventoryState.processUpload: LLSDAssetUploadError resperror = new LLSDAssetUploadError(); resperror.message = "Uploader busy processing previus request"; resperror.identifier = UUID.Zero; LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); errorResponse.uploader = ""; errorResponse.state = "error"; errorResponse.error = resperror; return errorResponse; break; case FileAgentInventoryState.waitUpload: // todo stop current uploader server break; case FileAgentInventoryState.idle: default: break; } m_FileAgentInventoryState = FileAgentInventoryState.processRequest; } int cost = 0; int nreqtextures = 0; int nreqmeshs= 0; int nreqinstances = 0; bool IsAtestUpload = false; string assetName = llsdRequest.name; LLSDAssetUploadResponseData meshcostdata = new LLSDAssetUploadResponseData(); if (llsdRequest.asset_type == "texture" || llsdRequest.asset_type == "animation" || llsdRequest.asset_type == "animatn" || // this is the asset name actually used by viewers llsdRequest.asset_type == "mesh" || llsdRequest.asset_type == "sound") { ScenePresence avatar = null; m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar); // check user level if (avatar != null) { if (avatar.UserLevel < m_levelUpload) { LLSDAssetUploadError resperror = new LLSDAssetUploadError(); resperror.message = "Insufficient permissions to upload"; resperror.identifier = UUID.Zero; LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); errorResponse.uploader = ""; errorResponse.state = "error"; errorResponse.error = resperror; lock (m_ModelCost) m_FileAgentInventoryState = FileAgentInventoryState.idle; return errorResponse; } } // check test upload and funds if (client != null) { IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>(); int baseCost = 0; if (mm != null) baseCost = mm.UploadCharge; string warning = String.Empty; if (llsdRequest.asset_type == "mesh") { string error; int modelcost; if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost, meshcostdata, out error, ref warning)) { LLSDAssetUploadError resperror = new LLSDAssetUploadError(); resperror.message = error; resperror.identifier = UUID.Zero; LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); errorResponse.uploader = ""; errorResponse.state = "error"; errorResponse.error = resperror; lock (m_ModelCost) m_FileAgentInventoryState = FileAgentInventoryState.idle; return errorResponse; } cost = modelcost; } else { cost = baseCost; } if (cost > 0 && mm != null) { // check for test upload if (m_ForceFreeTestUpload) // all are test { if (!(assetName.Length > 5 && assetName.StartsWith("TEST-"))) // has normal name lets change it assetName = "TEST-" + assetName; IsAtestUpload = true; } else if (m_enableFreeTestUpload) // only if prefixed with "TEST-" { IsAtestUpload = (assetName.Length > 5 && assetName.StartsWith("TEST-")); } if(IsAtestUpload) // let user know, still showing cost estimation warning += "Upload will have no cost, for testing purposes only. Other uses are prohibited. Items will not work after 48 hours or on other regions"; // check funds else { if (!mm.UploadCovered(client.AgentId, (int)cost)) { LLSDAssetUploadError resperror = new LLSDAssetUploadError(); resperror.message = "Insuficient funds"; resperror.identifier = UUID.Zero; LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); errorResponse.uploader = ""; errorResponse.state = "error"; errorResponse.error = resperror; lock (m_ModelCost) m_FileAgentInventoryState = FileAgentInventoryState.idle; return errorResponse; } } } if (client != null && warning != String.Empty) client.SendAgentAlertMessage(warning, true); } } string assetDes = llsdRequest.description; string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; UUID newAsset = UUID.Random(); UUID newInvItem = UUID.Random(); UUID parentFolder = llsdRequest.folder_id; string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); UUID texturesFolder = UUID.Zero; if(!IsAtestUpload && m_enableModelUploadTextureToInventory) texturesFolder = llsdRequest.texture_folder_id; AssetUploader uploader = new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost, texturesFolder, nreqtextures, nreqmeshs, nreqinstances, IsAtestUpload, llsdRequest.next_owner_mask, llsdRequest.group_mask, llsdRequest.everyone_mask); m_HostCapsObj.HttpListener.AddStreamHandler( new BinaryStreamHandler( "POST", capsBase + uploaderPath, uploader.uploaderCaps, "NewAgentInventoryRequest", m_HostCapsObj.AgentID.ToString())); string protocol = "http://"; if (m_HostCapsObj.SSLCaps) protocol = "https://"; string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase + uploaderPath; LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); uploadResponse.uploader = uploaderURL; uploadResponse.state = "upload"; uploadResponse.upload_price = (int)cost; if (llsdRequest.asset_type == "mesh") { uploadResponse.data = meshcostdata; } uploader.OnUpLoad += UploadCompleteHandler; lock (m_ModelCost) m_FileAgentInventoryState = FileAgentInventoryState.waitUpload; return uploadResponse; }