Ejemplo n.º 1
0
        // calculates a mesh model costs
        // returns false on error, with a reason on parameter error
        // resources input LLSD request
        // basicCost input region assets upload cost
        // totalcost returns model total upload fee
        // meshcostdata returns detailed costs for viewer 
        // avatarSkeleton if mesh includes a avatar skeleton
        // useAvatarCollider if we should use physics mesh for avatar
        public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost,
            LLSDAssetUploadResponseData meshcostdata, out string error, ref string warning)
        {
            totalcost = 0;
            error = string.Empty;

            bool avatarSkeleton = false;
            
            if (resources == null ||
                resources.instance_list == null ||
                resources.instance_list.Array.Count == 0)
            {
                error = "missing model information.";
                return false;
            }

            int numberInstances = resources.instance_list.Array.Count;

            if (ObjectLinkedPartsMax != 0 && numberInstances > ObjectLinkedPartsMax)
            {
                error = "Model would have more than " + ObjectLinkedPartsMax.ToString() + " linked prims";
                return false;
            }

            meshcostdata.model_streaming_cost = 0.0;
            meshcostdata.simulation_cost = 0.0;
            meshcostdata.physics_cost = 0.0;
            meshcostdata.resource_cost = 0.0;

            meshcostdata.upload_price_breakdown.mesh_instance = 0;
            meshcostdata.upload_price_breakdown.mesh_physics = 0;
            meshcostdata.upload_price_breakdown.mesh_streaming = 0;
            meshcostdata.upload_price_breakdown.model = 0;

            int itmp;

            // textures cost
            if (resources.texture_list != null && resources.texture_list.Array.Count > 0)
            {
                float textures_cost = (float)(resources.texture_list.Array.Count * basicCost);
                textures_cost *= ModelTextureCostFactor;

                itmp = (int)(textures_cost + 0.5f); // round
                meshcostdata.upload_price_breakdown.texture = itmp;
                totalcost += itmp;
            }

            // meshs assets cost
            float meshsfee = 0;
            int numberMeshs = 0;
            bool haveMeshs = false;

            bool curskeleton;
            bool curAvatarPhys;

            List<ameshCostParam> meshsCosts = new List<ameshCostParam>();

            if (resources.mesh_list != null && resources.mesh_list.Array.Count > 0)
            {
                numberMeshs = resources.mesh_list.Array.Count;
                
                for (int i = 0; i < numberMeshs; i++)
                {
                    ameshCostParam curCost = new ameshCostParam();
                    byte[] data = (byte[])resources.mesh_list.Array[i];

                    if (!MeshCost(data, curCost,out curskeleton, out curAvatarPhys, out error))
                    {
                        return false;
                    }

                    if (curskeleton)
                    {
                        if (avatarSkeleton)
                        {
                            error = "model can only contain a avatar skeleton";
                            return false;
                        }
                        avatarSkeleton = true;
                    }
                    meshsCosts.Add(curCost);
                    meshsfee += curCost.costFee;
                }
                haveMeshs = true;
            }

            // instances (prims) cost
            

            int mesh;
            int skipedSmall = 0;
            for (int i = 0; i < numberInstances; i++)
            {
                Hashtable inst = (Hashtable)resources.instance_list.Array[i];

                ArrayList ascale = (ArrayList)inst["scale"];
                Vector3 scale;
                double tmp;
                tmp = (double)ascale[0];
                scale.X = (float)tmp;
                tmp = (double)ascale[1];
                scale.Y = (float)tmp;
                tmp = (double)ascale[2];
                scale.Z = (float)tmp;

                if (scale.X < PrimScaleMin || scale.Y < PrimScaleMin || scale.Z < PrimScaleMin)
                {
                    skipedSmall++;
                    continue;
                }

                if (scale.X > NonPhysicalPrimScaleMax || scale.Y > NonPhysicalPrimScaleMax || scale.Z > NonPhysicalPrimScaleMax)
                {
                    error = "Model contains parts with sides larger than " + NonPhysicalPrimScaleMax.ToString() + "m. Please ajust scale";
                    return false;
                }

                if (haveMeshs && inst.ContainsKey("mesh"))
                {
                    mesh = (int)inst["mesh"];

                    if (mesh >= numberMeshs)
                    {
                        error = "Incoerent model information.";
                        return false;
                    }

                    // streamming cost

                    float sqdiam = scale.LengthSquared();

                    ameshCostParam curCost = meshsCosts[mesh];
                    float mesh_streaming = streamingCost(curCost, sqdiam);

                    meshcostdata.model_streaming_cost += mesh_streaming;
                    meshcostdata.physics_cost += curCost.physicsCost;
                }
                else // instance as no mesh ??
                {
                    // to do later if needed
                    meshcostdata.model_streaming_cost += 0.5f;
                    meshcostdata.physics_cost += 1.0f;
                }

                // assume unscripted and static prim server cost
                meshcostdata.simulation_cost += 0.5f;
                // charge for prims creation
                meshsfee += primCreationCost;
            }

            if (skipedSmall > 0)
            {
                if (skipedSmall > numberInstances / 2)
                {
                    error = "Model contains too many prims smaller than " + PrimScaleMin.ToString() +
                        "m minimum allowed size. Please check scalling";
                    return false;
                }
                else
                    warning += skipedSmall.ToString() + " of the requested " +numberInstances.ToString() +
                        " model prims will not upload because they are smaller than " + PrimScaleMin.ToString() +
                        "m minimum allowed size. Please check scalling ";
            }

            if (meshcostdata.physics_cost <= meshcostdata.model_streaming_cost)
                meshcostdata.resource_cost = meshcostdata.model_streaming_cost;
            else
                meshcostdata.resource_cost = meshcostdata.physics_cost;

            if (meshcostdata.resource_cost < meshcostdata.simulation_cost)
                meshcostdata.resource_cost = meshcostdata.simulation_cost;

            // scale cost
            // at this point a cost of 1.0 whould mean basic cost
            meshsfee *= ModelMeshCostFactor;

            if (meshsfee < ModelMinCostFactor)
                meshsfee = ModelMinCostFactor;

            // actually scale it to basic cost
            meshsfee *= (float)basicCost;

            meshsfee += 0.5f; // rounding

            totalcost += (int)meshsfee;

            // breakdown prices
            // don't seem to be in use so removed code for now
            
            return true;
        }
Ejemplo n.º 2
0
        /// <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;
        }