diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index 7b4e9571c7..c275d87c34 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -187,7 +187,11 @@ namespace OpenSim.Capabilities.Handlers
response["headers"] = headers;
string range = String.Empty;
- if (((Hashtable)request["headers"])["Range"] != null)
+
+ if (((Hashtable)request["headers"])["range"] != null)
+ range = (string)((Hashtable)request["headers"])["range"];
+
+ else if (((Hashtable)request["headers"])["Range"] != null)
range = (string)((Hashtable)request["headers"])["Range"];
if (!String.IsNullOrEmpty(range)) // JP2's only
@@ -227,17 +231,22 @@ namespace OpenSim.Capabilities.Handlers
// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
- // Always return PartialContent, even if the range covered the entire data length
- // We were accidentally sending back 404 before in this situation
- // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
- // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
- response["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent;
response["content-type"] = texture.Metadata.ContentType;
- headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length);
-
- byte[] d = new byte[len];
- Array.Copy(texture.Data, start, d, 0, len);
- response["bin_response_data"] = d;
+
+ if (start == 0 && len == texture.Data.Length) // well redudante maybe
+ {
+ response["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
+ response["bin_response_data"] = texture.Data;
+ }
+ else
+ {
+ response["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent;
+ headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length);
+
+ byte[] d = new byte[len];
+ Array.Copy(texture.Data, start, d, 0, len);
+ response["bin_response_data"] = d;
+ }
// response.Body.Write(texture.Data, start, len);
}
}
diff --git a/OpenSim/Capabilities/LLSDAssetUploadComplete.cs b/OpenSim/Capabilities/LLSDAssetUploadComplete.cs
index ab6cee55b7..ae8eb09345 100644
--- a/OpenSim/Capabilities/LLSDAssetUploadComplete.cs
+++ b/OpenSim/Capabilities/LLSDAssetUploadComplete.cs
@@ -30,12 +30,15 @@ using OpenMetaverse;
namespace OpenSim.Framework.Capabilities
{
+
[LLSDType("MAP")]
public class LLSDAssetUploadComplete
{
public string new_asset = String.Empty;
public UUID new_inventory_item = UUID.Zero;
+// public UUID new_texture_folder_id = UUID.Zero;
public string state = String.Empty;
+ public LLSDAssetUploadError error = null;
//public bool success = false;
public LLSDAssetUploadComplete()
diff --git a/OpenSim/Capabilities/LLSDAssetUploadRequest.cs b/OpenSim/Capabilities/LLSDAssetUploadRequest.cs
index f981bf0fc1..6779cc1fce 100644
--- a/OpenSim/Capabilities/LLSDAssetUploadRequest.cs
+++ b/OpenSim/Capabilities/LLSDAssetUploadRequest.cs
@@ -45,6 +45,10 @@ namespace OpenSim.Framework.Capabilities
public string asset_type = String.Empty;
public string description = String.Empty;
public UUID folder_id = UUID.Zero;
+ public UUID texture_folder_id = UUID.Zero;
+ public int next_owner_mask = 0;
+ public int group_mask = 0;
+ public int everyone_mask = 0;
public string inventory_type = String.Empty;
public string name = String.Empty;
public LLSDAssetResource asset_resources = new LLSDAssetResource();
diff --git a/OpenSim/Capabilities/LLSDAssetUploadResponse.cs b/OpenSim/Capabilities/LLSDAssetUploadResponse.cs
index 18285b581f..7c4bc97476 100644
--- a/OpenSim/Capabilities/LLSDAssetUploadResponse.cs
+++ b/OpenSim/Capabilities/LLSDAssetUploadResponse.cs
@@ -26,9 +26,17 @@
*/
using System;
+using OpenMetaverse;
namespace OpenSim.Framework.Capabilities
{
+ [OSDMap]
+ public class LLSDAssetUploadError
+ {
+ public string message = String.Empty;
+ public UUID identifier = UUID.Zero;
+ }
+
[OSDMap]
public class LLSDAssetUploadResponsePricebrkDown
{
@@ -56,11 +64,13 @@ namespace OpenSim.Framework.Capabilities
public string state = String.Empty;
public int upload_price = 0;
public LLSDAssetUploadResponseData data = null;
+ public LLSDAssetUploadError error = null;
public LLSDAssetUploadResponse()
{
}
}
+
[OSDMap]
public class LLSDNewFileAngentInventoryVariablePriceReplyResponse
{
diff --git a/OpenSim/Framework/AssetBase.cs b/OpenSim/Framework/AssetBase.cs
index ff240bebb1..5da8e1130b 100644
--- a/OpenSim/Framework/AssetBase.cs
+++ b/OpenSim/Framework/AssetBase.cs
@@ -150,7 +150,8 @@ namespace OpenSim.Framework
Type == (sbyte)AssetType.SnapshotFolder ||
Type == (sbyte)AssetType.TrashFolder ||
Type == (sbyte)AssetType.ImageJPEG ||
- Type == (sbyte) AssetType.ImageTGA ||
+ Type == (sbyte)AssetType.ImageTGA ||
+ Type == (sbyte)AssetType.Mesh ||
Type == (sbyte) AssetType.LSLBytecode);
}
}
diff --git a/OpenSim/Framework/Console/RemoteConsole.cs b/OpenSim/Framework/Console/RemoteConsole.cs
index 50eb1734a5..3e3c2b3758 100644
--- a/OpenSim/Framework/Console/RemoteConsole.cs
+++ b/OpenSim/Framework/Console/RemoteConsole.cs
@@ -425,7 +425,7 @@ namespace OpenSim.Framework.Console
return false;
}
- private Hashtable GetEvents(UUID RequestID, UUID sessionID, string request)
+ private Hashtable GetEvents(UUID RequestID, UUID sessionID)
{
ConsoleConnection c = null;
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 91f36a5dff..4ae533ec4d 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -1171,6 +1171,7 @@ namespace OpenSim.Framework
///
///
void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId);
+ void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId);
void SendRemoveInventoryItem(UUID itemID);
diff --git a/OpenSim/Framework/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs
index e7a7f7f13c..e4f1111e02 100644
--- a/OpenSim/Framework/PriorityQueue.cs
+++ b/OpenSim/Framework/PriorityQueue.cs
@@ -45,7 +45,8 @@ namespace OpenSim.Framework
///
/// Total number of queues (priorities) available
///
- public const uint NumberOfQueues = 12;
+
+ public const uint NumberOfQueues = 12; // includes immediate queues, m_queueCounts need to be set acording
///
/// Number of queuest (priorities) that are processed immediately
@@ -60,7 +61,8 @@ namespace OpenSim.Framework
// each pass. weighted towards the higher priority queues
private uint m_nextQueue = 0;
private uint m_countFromQueue = 0;
- private uint[] m_queueCounts = { 8, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1 };
+ // first queues are imediate, so no counts
+ private uint[] m_queueCounts = {0, 0, 8, 4, 4, 2, 2, 2, 2, 1, 1, 1};
// next request is a counter of the number of updates queued, it provides
// a total ordering on the updates coming through the queue and is more
@@ -137,7 +139,7 @@ namespace OpenSim.Framework
///
public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue)
{
- // If there is anything in priority queue 0, return it first no
+ // If there is anything in imediate queues, return it first no
// matter what else. Breaks fairness. But very useful.
for (int iq = 0; iq < NumberOfImmediateQueues; iq++)
{
@@ -172,14 +174,13 @@ namespace OpenSim.Framework
}
// Find the next non-immediate queue with updates in it
- for (int i = 0; i < NumberOfQueues; ++i)
+ for (uint i = NumberOfImmediateQueues; i < NumberOfQueues; ++i)
{
- m_nextQueue = (uint)((m_nextQueue + 1) % NumberOfQueues);
- m_countFromQueue = m_queueCounts[m_nextQueue];
+ m_nextQueue++;
+ if(m_nextQueue >= NumberOfQueues)
+ m_nextQueue = NumberOfImmediateQueues;
- // if this is one of the immediate queues, just skip it
- if (m_nextQueue < NumberOfImmediateQueues)
- continue;
+ m_countFromQueue = m_queueCounts[m_nextQueue];
if (m_heaps[m_nextQueue].Count > 0)
{
@@ -189,7 +190,6 @@ namespace OpenSim.Framework
m_lookupTable.Remove(item.Value.Entity.LocalId);
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
value = item.Value;
-
return true;
}
}
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 29593e5815..1d35b1ac10 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -334,6 +334,7 @@ namespace OpenSim.Framework.Servers.HttpServer
StreamReader reader = new StreamReader(requestStream, encoding);
string requestBody = reader.ReadToEnd();
+ reader.Close();
Hashtable keysvals = new Hashtable();
Hashtable headervals = new Hashtable();
@@ -648,7 +649,7 @@ namespace OpenSim.Framework.Servers.HttpServer
// Every month or so this will wrap and give bad numbers, not really a problem
// since its just for reporting
int tickdiff = requestEndTick - requestStartTick;
- if (tickdiff > 3000 && requestHandler.Name != "GetTexture")
+ if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture"))
{
m_log.InfoFormat(
"[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms",
@@ -1555,6 +1556,8 @@ namespace OpenSim.Framework.Servers.HttpServer
else
responseString = (string)responsedata["str_response_string"];
contentType = (string)responsedata["content_type"];
+ if (responseString == null)
+ responseString = String.Empty;
}
catch
{
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
index a80b1d79fa..d0a37d0f81 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
@@ -34,7 +34,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public delegate void RequestMethod(UUID requestID, Hashtable request);
public delegate bool HasEventsMethod(UUID requestID, UUID pId);
- public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId, string request);
+ public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId);
public delegate Hashtable NoEventsMethod(UUID requestID, UUID pId);
@@ -46,7 +46,7 @@ namespace OpenSim.Framework.Servers.HttpServer
public RequestMethod Request;
public UUID Id;
public int TimeOutms;
- public EventType Type;
+ public EventType Type;
public enum EventType : int
{
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index db088e75a2..4be8bf40d9 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -33,6 +33,7 @@ using log4net;
using HttpServer;
using OpenSim.Framework;
using OpenSim.Framework.Monitoring;
+using Amib.Threading;
/*
@@ -185,6 +186,8 @@ namespace OpenSim.Framework.Servers.HttpServer
private bool m_running = true;
private int slowCount = 0;
+ private SmartThreadPool m_threadPool = new SmartThreadPool(20000, 12, 2);
+
// private int m_timeout = 1000; // increase timeout 250; now use the event one
public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout)
@@ -202,7 +205,7 @@ namespace OpenSim.Framework.Servers.HttpServer
String.Format("PollServiceWorkerThread{0}", i),
ThreadPriority.Normal,
false,
- true,
+ false,
null,
int.MaxValue);
}
@@ -275,15 +278,7 @@ namespace OpenSim.Framework.Servers.HttpServer
Thread.Sleep(1000); // let the world move
foreach (Thread t in m_workerThreads)
- {
- try
- {
- t.Abort();
- }
- catch
- {
- }
- }
+ Watchdog.AbortThread(t.ManagedThreadId);
try
{
@@ -326,13 +321,9 @@ namespace OpenSim.Framework.Servers.HttpServer
private void PoolWorkerJob()
{
- PollServiceHttpRequest req;
- StreamReader str;
-
-// while (true)
while (m_running)
{
- req = m_requests.Dequeue(5000);
+ PollServiceHttpRequest req = m_requests.Dequeue(5000);
Watchdog.UpdateThread();
if (req != null)
@@ -341,35 +332,41 @@ namespace OpenSim.Framework.Servers.HttpServer
{
if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
{
- try
- {
- str = new StreamReader(req.Request.Body);
- }
- catch (System.ArgumentException)
- {
- // Stream was not readable means a child agent
- // was closed due to logout, leaving the
- // Event Queue request orphaned.
+ Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
+
+ if (responsedata == null)
continue;
- }
- try
+ if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.Normal)
{
- Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id, str.ReadToEnd());
- DoHTTPGruntWork(m_server, req, responsedata);
+ try
+ {
+ DoHTTPGruntWork(m_server, req, responsedata);
+ }
+ catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
+ {
+ // Ignore it, no need to reply
+ }
}
- catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
+ else
{
- // Ignore it, no need to reply
+ m_threadPool.QueueWorkItem(x =>
+ {
+ try
+ {
+ DoHTTPGruntWork(m_server, req, responsedata);
+ }
+ catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
+ {
+ // Ignore it, no need to reply
+ }
+
+ return null;
+ }, null);
}
-
- str.Close();
-
}
else
{
-// if ((Environment.TickCount - req.RequestTime) > m_timeout)
-
if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
{
DoHTTPGruntWork(m_server, req,
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 580c005322..c705f101ea 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -54,8 +54,10 @@ using OSDMap = OpenMetaverse.StructuredData.OSDMap;
namespace OpenSim.Region.ClientStack.Linden
{
public delegate void UpLoadedAsset(
- string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder,
- byte[] data, string inventoryType, string assetType);
+ string assetName, string description, 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);
public delegate UUID UpdateItem(UUID itemID, byte[] data);
@@ -87,6 +89,7 @@ namespace OpenSim.Region.ClientStack.Linden
private Scene m_Scene;
private Caps m_HostCapsObj;
+ private ModelCost m_ModelCost;
private static readonly string m_requestPath = "0000/";
// private static readonly string m_mapLayerPath = "0001/";
@@ -115,12 +118,50 @@ namespace OpenSim.Region.ClientStack.Linden
private IAssetService m_assetService;
private bool m_dumpAssetsToFile = false;
private string m_regionName;
+
private int m_levelUpload = 0;
+ private bool m_enableFreeTestUpload = false; // allows "TEST-" prefix hack
+ private bool m_ForceFreeTestUpload = false; // forces all uploads to be test
+
+ private bool m_enableModelUploadTextureToInventory = false; // place uploaded textures also in inventory
+ // may not be visible till relog
+
+ private bool m_RestrictFreeTestUploadPerms = false; // reduces also the permitions. Needs a creator defined!!
+ private UUID m_testAssetsCreatorID = UUID.Zero;
+
+ private float m_PrimScaleMin = 0.001f;
+
+ private enum FileAgentInventoryState : int
+ {
+ idle = 0,
+ processRequest = 1,
+ waitUpload = 2,
+ processUpload = 3
+ }
+ private FileAgentInventoryState 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_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)
{
@@ -135,6 +176,37 @@ namespace OpenSim.Region.ClientStack.Linden
{
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;
@@ -146,6 +218,8 @@ namespace OpenSim.Region.ClientStack.Linden
ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset;
TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset;
GetClient = m_Scene.SceneGraph.GetControllingClient;
+
+ m_FileAgentInventoryState = FileAgentInventoryState.idle;
}
///
@@ -191,7 +265,6 @@ namespace OpenSim.Region.ClientStack.Linden
{
try
{
- // I don't think this one works...
m_HostCapsObj.RegisterHandler(
"NewFileAgentInventory",
new LLSDStreamhandler(
@@ -213,9 +286,7 @@ namespace OpenSim.Region.ClientStack.Linden
IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost);
m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler);
IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected);
- m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler);
-
-
+ m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler);
m_HostCapsObj.RegisterHandler(
"CopyInventoryFromNotecard",
@@ -387,37 +458,6 @@ namespace OpenSim.Region.ClientStack.Linden
return UUID.Zero;
}
- private delegate void UploadWithCostCompleteDelegate(string assetName,
- string assetDescription, UUID assetID, UUID inventoryItem,
- UUID parentFolder, byte[] data, string inventoryType,
- string assetType, uint cost);
-
- private class AssetUploaderWithCost : AssetUploader
- {
- private uint m_cost;
-
- public event UploadWithCostCompleteDelegate OnUpLoad;
-
- public AssetUploaderWithCost(string assetName, string description, UUID assetID,
- UUID inventoryItem, UUID parentFolderID, string invType, string assetType,
- string path, IHttpServer httpServer, bool dumpAssetsToFile, uint cost) :
- base(assetName, description, assetID, inventoryItem, parentFolderID,
- invType, assetType, path, httpServer, dumpAssetsToFile)
- {
- m_cost = cost;
-
- base.OnUpLoad += UploadCompleteHandler;
- }
-
- private void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
- UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
- string assetType)
- {
- OnUpLoad(assetName, assetDescription, assetID, inventoryItem, parentFolder,
- data, inventoryType, assetType, m_cost);
- }
- }
-
///
///
///
@@ -428,7 +468,47 @@ namespace OpenSim.Region.ClientStack.Linden
//m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
//m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);
- uint cost = 0;
+ // 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" ||
@@ -436,83 +516,128 @@ namespace OpenSim.Region.ClientStack.Linden
llsdRequest.asset_type == "sound")
{
ScenePresence avatar = null;
- IClientAPI client = null;
m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar);
// check user level
if (avatar != null)
{
- client = avatar.ControllingClient;
-
if (avatar.UserLevel < m_levelUpload)
{
- if (client != null)
- client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false);
+ 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 funds
+ // check test upload and funds
if (client != null)
{
IMoneyModule mm = m_Scene.RequestModuleInterface();
+ int baseCost = 0;
if (mm != null)
+ baseCost = mm.UploadCharge;
+
+ string warning = String.Empty;
+
+ if (llsdRequest.asset_type == "mesh")
{
- // XPTO: The cost should be calculated about here
-
- if (llsdRequest.asset_type == "mesh")
+ string error;
+ int modelcost;
+
+ if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost,
+ meshcostdata, out error, ref warning))
{
- cost += 20; // Constant for now to test showing a price
-
- if (llsdRequest.asset_resources == null)
- {
- client.SendAgentAlertMessage("Unable to upload asset. missing information.", false);
-
- LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
- errorResponse.uploader = "";
- errorResponse.state = "error";
- return errorResponse;
- }
-
- uint textures_cost = (uint)llsdRequest.asset_resources.texture_list.Array.Count;
- textures_cost *= (uint)mm.UploadCharge;
-
- cost += textures_cost;
- }
- else
- {
- cost = (uint)mm.UploadCharge;
- }
-
- if (!mm.UploadCovered(client.AgentId, (int)cost))
- {
- client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false);
+ 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 assetName = llsdRequest.name;
+
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;
- AssetUploaderWithCost uploader =
- new AssetUploaderWithCost(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
- llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost);
+ 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);
m_HostCapsObj.HttpListener.AddStreamHandler(
new BinaryStreamHandler(
@@ -536,25 +661,17 @@ namespace OpenSim.Region.ClientStack.Linden
uploadResponse.state = "upload";
uploadResponse.upload_price = (int)cost;
- // use fake values for now
if (llsdRequest.asset_type == "mesh")
{
- uploadResponse.data = new LLSDAssetUploadResponseData();
- uploadResponse.data.model_streaming_cost = 1.0;
- uploadResponse.data.simulation_cost = 1.5;
-
- uploadResponse.data.physics_cost = 2.0;
- uploadResponse.data.resource_cost = 3.0;
- uploadResponse.data.upload_price_breakdown.mesh_instance = 1;
- uploadResponse.data.upload_price_breakdown.mesh_physics = 2;
- uploadResponse.data.upload_price_breakdown.mesh_streaming = 3;
- uploadResponse.data.upload_price_breakdown.texture = 5;
- uploadResponse.data.upload_price_breakdown.model = 4;
+ uploadResponse.data = meshcostdata;
}
uploader.OnUpLoad += UploadCompleteHandler;
- return uploadResponse;
+ lock (m_ModelCost)
+ m_FileAgentInventoryState = FileAgentInventoryState.waitUpload;
+
+ return uploadResponse;
}
///
@@ -565,8 +682,14 @@ namespace OpenSim.Region.ClientStack.Linden
///
public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
- string assetType, uint cost)
+ string assetType, int cost,
+ UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
+ bool IsAtestUpload, ref string error)
{
+
+ 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);
@@ -574,117 +697,247 @@ namespace OpenSim.Region.ClientStack.Linden
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();
+ 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 = 1;
- assType = 1;
+ inType = (sbyte)InventoryType.Sound;
+ assType = (sbyte)AssetType.Sound;
}
else if (inventoryType == "animation")
{
- inType = 19;
- assType = 20;
+ inType = (sbyte)InventoryType.Animation;
+ assType = (sbyte)AssetType.Animation;
}
else if (inventoryType == "wearable")
{
- inType = 18;
+ inType = (sbyte)InventoryType.Wearable;
switch (assetType)
{
case "bodypart":
- assType = 13;
+ assType = (sbyte)AssetType.Bodypart;
break;
case "clothing":
- assType = 5;
+ assType = (sbyte)AssetType.Clothing;
break;
}
}
else if (inventoryType == "object")
{
- inType = (sbyte)InventoryType.Object;
- assType = (sbyte)AssetType.Object;
-
- List positions = new List();
- List rotations = new List();
- OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
- OSDArray instance_list = (OSDArray)request["instance_list"];
- OSDArray mesh_list = (OSDArray)request["mesh_list"];
- OSDArray texture_list = (OSDArray)request["texture_list"];
- SceneObjectGroup grp = null;
-
- List textures = new List();
- for (int i = 0; i < texture_list.Count; i++)
+ if (assetType == "mesh") // this code for now is for mesh models uploads only
{
- AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, "");
- textureAsset.Data = texture_list[i].AsBinary();
- m_assetService.Store(textureAsset);
- textures.Add(textureAsset.FullID);
- }
+ inType = (sbyte)InventoryType.Object;
+ assType = (sbyte)AssetType.Object;
- for (int i = 0; i < mesh_list.Count; i++)
- {
- PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
+ List positions = new List();
+ List rotations = new List();
+ OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
- Primitive.TextureEntry textureEntry
- = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
- OSDMap inner_instance_list = (OSDMap)instance_list[i];
+ // compare and get updated information
- OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
- for (uint face = 0; face < face_list.Count; face++)
+ bool mismatchError = true;
+
+ while (mismatchError)
{
- 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;
+ mismatchError = false;
}
- pbs.TextureEntry = textureEntry.GetBytes();
+ if (mismatchError)
+ {
+ error = "Upload and fee estimation information don't match";
+ lock (m_ModelCost)
+ m_FileAgentInventoryState = FileAgentInventoryState.idle;
- AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, "");
- meshAsset.Data = mesh_list[i].AsBinary();
- m_assetService.Store(meshAsset);
+ return;
+ }
- pbs.SculptEntry = true;
- pbs.SculptTexture = meshAsset.FullID;
- pbs.SculptType = (byte)SculptType.Mesh;
- pbs.SculptData = meshAsset.Data;
+ OSDArray instance_list = (OSDArray)request["instance_list"];
+ OSDArray mesh_list = (OSDArray)request["mesh_list"];
+ OSDArray texture_list = (OSDArray)request["texture_list"];
+ SceneObjectGroup grp = null;
- Vector3 position = inner_instance_list["position"].AsVector3();
- Vector3 scale = inner_instance_list["scale"].AsVector3();
- Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
+ // create and store texture assets
+ bool doTextInv = (!istest && m_enableModelUploadTextureToInventory &&
+ texturesFolder != UUID.Zero);
+
+
+ List textures = new List();
+
+
+ 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);
+
+ texitem.BasePermissions = (uint)PermissionMask.All;
+ 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 meshAssets = new List();
+ for (int i = 0; i < mesh_list.Count; i++)
+ {
+ 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);
+ }
+
+ 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.prim; // default for mesh is simple convex
+ if(hasmesh)
+ physicsShapeType = (byte) PhysShapeType.convex; // default for mesh is simple convex
+// int material = inner_instance_list["material"].AsInteger();
+ byte material = (byte)Material.Wood;
// no longer used - begin ------------------------
-// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
-// int material = inner_instance_list["material"].AsInteger();
// int mesh = inner_instance_list["mesh"].AsInteger();
// OSDMap permissions = (OSDMap)inner_instance_list["permissions"];
@@ -699,24 +952,42 @@ namespace OpenSim.Region.ClientStack.Linden
// UUID owner_id = permissions["owner_id"].AsUUID();
// int owner_mask = permissions["owner_mask"].AsInteger();
// no longer used - end ------------------------
+
- UUID owner_id = m_HostCapsObj.AgentID;
+ SceneObjectPart prim
+ = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);
- 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.Scale = scale;
- prim.OffsetPosition = position;
- rotations.Add(rotation);
- positions.Add(position);
- prim.UUID = UUID.Random();
- prim.CreatorID = owner_id;
- prim.OwnerID = owner_id;
- prim.GroupID = UUID.Zero;
- prim.LastOwnerID = prim.OwnerID;
- prim.CreationDate = Util.UnixTimeSinceEpoch();
- prim.Name = assetName;
- prim.Description = "";
+ if (restrictPerms)
+ {
+ prim.BaseMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
+ prim.EveryoneMask = 0;
+ prim.GroupMask = 0;
+ prim.NextOwnerMask = 0;
+ prim.OwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
+ }
+
+ 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;
@@ -724,37 +995,64 @@ namespace OpenSim.Region.ClientStack.Linden
// prim.NextOwnerMask = (uint)next_owner_mask;
// prim.OwnerMask = (uint)owner_mask;
- if (grp == null)
- grp = new SceneObjectGroup(prim);
+ 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.AddPart(prim);
+ {
+ grp.AbsolutePosition = rootPos;
+ grp.UpdateGroupRotationR(rotations[0]);
+ }
+
+ data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
}
- // Fix first link number
- if (grp.Parts.Length > 1)
- grp.RootPart.LinkNum++;
-
- Vector3 rootPos = positions[0];
- grp.AbsolutePosition = rootPos;
- for (int i = 0; i < positions.Count; i++)
+ else // not a mesh model
{
- Vector3 offset = positions[i] - rootPos;
- grp.Parts[i].OffsetPosition = offset;
+ m_log.ErrorFormat("[CAPS Asset Upload] got unsuported assetType for object upload");
+ return;
}
-
- for (int i = 0; i < rotations.Count; i++)
- {
- if (i != 0)
- grp.Parts[i].RotationOffset = rotations[i];
- }
-
- grp.UpdateGroupRotationR(rotations[0]);
- data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
}
AssetBase asset;
- asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString());
+ 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)
@@ -762,11 +1060,17 @@ namespace OpenSim.Region.ClientStack.Linden
InventoryItemBase item = new InventoryItemBase();
item.Owner = m_HostCapsObj.AgentID;
- item.CreatorId = m_HostCapsObj.AgentID.ToString();
+ item.CreatorId = creatorIDstr;
item.CreatorData = String.Empty;
item.ID = inventoryItem;
item.AssetID = asset.FullID;
- item.Description = assetDescription;
+ 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;
@@ -774,18 +1078,60 @@ namespace OpenSim.Region.ClientStack.Linden
// 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.
- item.CurrentPermissions
- = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
- item.BasePermissions = (uint)PermissionMask.All;
- item.EveryOnePermissions = 0;
- item.NextPermissions = (uint)PermissionMask.All;
+ if (restrictPerms)
+ {
+ item.CurrentPermissions
+ = (uint)(PermissionMask.Move | PermissionMask.Modify);
+
+ item.BasePermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
+ item.EveryOnePermissions = 0;
+ item.NextPermissions = 0;
+ }
+ else
+ {
+ item.CurrentPermissions
+ = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
+
+ item.BasePermissions = (uint)PermissionMask.All;
+ item.EveryOnePermissions = 0;
+ item.NextPermissions = (uint)PermissionMask.All;
+ }
+
item.CreationDate = Util.UnixTimeSinceEpoch();
+ m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
+
if (AddNewInventoryItem != null)
{
- AddNewInventoryItem(m_HostCapsObj.AgentID, item, cost);
+ 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;
}
///
@@ -1098,6 +1444,7 @@ namespace OpenSim.Region.ClientStack.Linden
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
public event UpLoadedAsset OnUpLoad;
private UpLoadedAsset handlerUpLoad = null;
@@ -1112,11 +1459,21 @@ namespace OpenSim.Region.ClientStack.Linden
private string m_invType = String.Empty;
private string m_assetType = String.Empty;
+ private int m_cost;
+ private string m_error = String.Empty;
+
private Timer m_timeoutTimer = new Timer();
+ private UUID m_texturesFolder;
+ private int m_nreqtextures;
+ private int m_nreqmeshs;
+ private int m_nreqinstances;
+ private bool m_IsAtestUpload;
public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
UUID parentFolderID, string invType, string assetType, string path,
- IHttpServer httpServer, bool dumpAssetsToFile)
+ IHttpServer httpServer, bool dumpAssetsToFile,
+ int totalCost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
+ bool IsAtestUpload)
{
m_assetName = assetName;
m_assetDes = description;
@@ -1128,6 +1485,13 @@ namespace OpenSim.Region.ClientStack.Linden
m_assetType = assetType;
m_invType = invType;
m_dumpAssetsToFile = dumpAssetsToFile;
+ m_cost = totalCost;
+
+ m_texturesFolder = texturesFolder;
+ m_nreqtextures = nreqtextures;
+ m_nreqmeshs = nreqmeshs;
+ m_nreqinstances = nreqinstances;
+ m_IsAtestUpload = IsAtestUpload;
m_timeoutTimer.Elapsed += TimedOut;
m_timeoutTimer.Interval = 120000;
@@ -1147,14 +1511,15 @@ namespace OpenSim.Region.ClientStack.Linden
UUID inv = inventoryItemID;
string res = String.Empty;
LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
+/*
uploadComplete.new_asset = newAssetID.ToString();
uploadComplete.new_inventory_item = inv;
uploadComplete.state = "complete";
res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
-
- httpListener.RemoveStreamHandler("POST", uploaderPath);
+*/
m_timeoutTimer.Stop();
+ httpListener.RemoveStreamHandler("POST", uploaderPath);
// TODO: probably make this a better set of extensions here
string extension = ".jp2";
@@ -1170,9 +1535,40 @@ namespace OpenSim.Region.ClientStack.Linden
handlerUpLoad = OnUpLoad;
if (handlerUpLoad != null)
{
- handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType);
+ handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType,
+ m_cost, m_texturesFolder, m_nreqtextures, m_nreqmeshs, m_nreqinstances, m_IsAtestUpload, ref m_error);
+ }
+ if (m_IsAtestUpload)
+ {
+ LLSDAssetUploadError resperror = new LLSDAssetUploadError();
+ resperror.message = "Upload SUCESSEFULL for testing purposes only. Other uses are prohibited. Item will not work after 48 hours or on other regions";
+ resperror.identifier = inv;
+
+ uploadComplete.error = resperror;
+ uploadComplete.state = "Upload4Testing";
+ }
+ else
+ {
+ if (m_error == String.Empty)
+ {
+ uploadComplete.new_asset = newAssetID.ToString();
+ uploadComplete.new_inventory_item = inv;
+ // if (m_texturesFolder != UUID.Zero)
+ // uploadComplete.new_texture_folder_id = m_texturesFolder;
+ uploadComplete.state = "complete";
+ }
+ else
+ {
+ LLSDAssetUploadError resperror = new LLSDAssetUploadError();
+ resperror.message = m_error;
+ resperror.identifier = inv;
+
+ uploadComplete.error = resperror;
+ uploadComplete.state = "failed";
+ }
}
+ res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
return res;
}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
new file mode 100644
index 0000000000..4a3fae6066
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
@@ -0,0 +1,671 @@
+// Proprietary code of Avination Virtual Limited
+// (c) 2012 Melanie Thielker, Leal Duarte
+//
+
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+
+using OpenSim.Framework;
+using OpenSim.Region.Framework;
+using OpenSim.Region.Framework.Scenes;
+using OpenSim.Framework.Capabilities;
+
+using ComponentAce.Compression.Libs.zlib;
+
+using OSDArray = OpenMetaverse.StructuredData.OSDArray;
+using OSDMap = OpenMetaverse.StructuredData.OSDMap;
+
+namespace OpenSim.Region.ClientStack.Linden
+{
+ public struct ModelPrimLimits
+ {
+
+ }
+
+ public class ModelCost
+ {
+
+ // upload fee defaults
+ // fees are normalized to 1.0
+ // this parameters scale them to basic cost ( so 1.0 translates to 10 )
+
+ public float ModelMeshCostFactor = 0.0f; // scale total cost relative to basic (excluding textures)
+ public float ModelTextureCostFactor = 1.0f; // scale textures fee to basic.
+ public float ModelMinCostFactor = 0.0f; // 0.5f; // minimum total model free excluding textures
+
+ // itens costs in normalized values
+ // ie will be multiplied by basicCost and factors above
+ public float primCreationCost = 0.002f; // extra cost for each prim creation overhead
+ // weigthed size to normalized cost
+ public float bytecost = 1e-5f;
+
+ // mesh upload fees based on compressed data sizes
+ // several data sections are counted more that once
+ // to promote user optimization
+ // following parameters control how many extra times they are added
+ // to global size.
+ // LOD meshs
+ const float medSizeWth = 1f; // 2x
+ const float lowSizeWth = 1.5f; // 2.5x
+ const float lowestSizeWth = 2f; // 3x
+ // favor potencially physical optimized meshs versus automatic decomposition
+ const float physMeshSizeWth = 6f; // counts 7x
+ const float physHullSizeWth = 8f; // counts 9x
+
+ // stream cost area factors
+ // more or less like SL
+ const float highLodFactor = 17.36f;
+ const float midLodFactor = 277.78f;
+ const float lowLodFactor = 1111.11f;
+
+ // physics cost is below, identical to SL, assuming shape type convex
+ // server cost is below identical to SL assuming non scripted non physical object
+
+ // internal
+ const int bytesPerCoord = 6; // 3 coords, 2 bytes per each
+
+ // control prims dimensions
+ public float PrimScaleMin = 0.001f;
+ public float NonPhysicalPrimScaleMax = 256f;
+ public float PhysicalPrimScaleMax = 10f;
+ public int ObjectLinkedPartsMax = 512;
+
+ // storage for a single mesh asset cost parameters
+ private class ameshCostParam
+ {
+ // LOD sizes for size dependent streaming cost
+ public int highLODSize;
+ public int medLODSize;
+ public int lowLODSize;
+ public int lowestLODSize;
+ // normalized fee based on compressed data sizes
+ public float costFee;
+ // physics cost
+ public float physicsCost;
+ }
+
+ // 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
+ public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost,
+ LLSDAssetUploadResponseData meshcostdata, out string error, ref string warning)
+ {
+ totalcost = 0;
+ error = string.Empty;
+
+ 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( numberInstances > ObjectLinkedPartsMax )
+ {
+ error = "Model whould 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;
+ List meshsCosts = new List();
+
+ 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 error))
+ {
+ return false;
+ }
+ 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;
+ }
+
+ // single mesh asset cost
+ private bool MeshCost(byte[] data, ameshCostParam cost, out string error)
+ {
+ cost.highLODSize = 0;
+ cost.medLODSize = 0;
+ cost.lowLODSize = 0;
+ cost.lowestLODSize = 0;
+ cost.physicsCost = 0.0f;
+ cost.costFee = 0.0f;
+
+ error = string.Empty;
+
+ if (data == null || data.Length == 0)
+ {
+ error = "Missing model information.";
+ return false;
+ }
+
+ OSD meshOsd = null;
+ int start = 0;
+
+ error = "Invalid model data";
+
+ using (MemoryStream ms = new MemoryStream(data))
+ {
+ try
+ {
+ OSD osd = OSDParser.DeserializeLLSDBinary(ms);
+ if (osd is OSDMap)
+ meshOsd = (OSDMap)osd;
+ else
+ return false;
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ start = (int)ms.Position;
+ }
+
+ OSDMap map = (OSDMap)meshOsd;
+ OSDMap tmpmap;
+
+ int highlod_size = 0;
+ int medlod_size = 0;
+ int lowlod_size = 0;
+ int lowestlod_size = 0;
+ int skin_size = 0;
+
+ int hulls_size = 0;
+ int phys_nhulls;
+ int phys_hullsvertices = 0;
+
+ int physmesh_size = 0;
+ int phys_ntriangles = 0;
+
+ int submesh_offset = -1;
+
+ if (map.ContainsKey("physics_convex"))
+ {
+ tmpmap = (OSDMap)map["physics_convex"];
+ if (tmpmap.ContainsKey("offset"))
+ submesh_offset = tmpmap["offset"].AsInteger() + start;
+ if (tmpmap.ContainsKey("size"))
+ hulls_size = tmpmap["size"].AsInteger();
+ }
+
+ if (submesh_offset < 0 || hulls_size == 0)
+ {
+ error = "Missing physics_convex block";
+ return false;
+ }
+
+ if (!hulls(data, submesh_offset, hulls_size, out phys_hullsvertices, out phys_nhulls))
+ {
+ error = "Bad physics_convex block";
+ return false;
+ }
+
+ submesh_offset = -1;
+
+ // only look for LOD meshs sizes
+
+ if (map.ContainsKey("high_lod"))
+ {
+ tmpmap = (OSDMap)map["high_lod"];
+ // see at least if there is a offset for this one
+ if (tmpmap.ContainsKey("offset"))
+ submesh_offset = tmpmap["offset"].AsInteger() + start;
+ if (tmpmap.ContainsKey("size"))
+ highlod_size = tmpmap["size"].AsInteger();
+ }
+
+ if (submesh_offset < 0 || highlod_size <= 0)
+ {
+ error = "Missing high_lod block";
+ return false;
+ }
+
+ bool haveprev = true;
+
+ if (map.ContainsKey("medium_lod"))
+ {
+ tmpmap = (OSDMap)map["medium_lod"];
+ if (tmpmap.ContainsKey("size"))
+ medlod_size = tmpmap["size"].AsInteger();
+ else
+ haveprev = false;
+ }
+
+ if (haveprev && map.ContainsKey("low_lod"))
+ {
+ tmpmap = (OSDMap)map["low_lod"];
+ if (tmpmap.ContainsKey("size"))
+ lowlod_size = tmpmap["size"].AsInteger();
+ else
+ haveprev = false;
+ }
+
+ if (haveprev && map.ContainsKey("lowest_lod"))
+ {
+ tmpmap = (OSDMap)map["lowest_lod"];
+ if (tmpmap.ContainsKey("size"))
+ lowestlod_size = tmpmap["size"].AsInteger();
+ }
+
+ if (map.ContainsKey("skin"))
+ {
+ tmpmap = (OSDMap)map["skin"];
+ if (tmpmap.ContainsKey("size"))
+ skin_size = tmpmap["size"].AsInteger();
+ }
+
+ cost.highLODSize = highlod_size;
+ cost.medLODSize = medlod_size;
+ cost.lowLODSize = lowlod_size;
+ cost.lowestLODSize = lowestlod_size;
+
+ submesh_offset = -1;
+
+ tmpmap = null;
+ if(map.ContainsKey("physics_mesh"))
+ tmpmap = (OSDMap)map["physics_mesh"];
+ else if (map.ContainsKey("physics_shape")) // old naming
+ tmpmap = (OSDMap)map["physics_shape"];
+
+ if(tmpmap != null)
+ {
+ if (tmpmap.ContainsKey("offset"))
+ submesh_offset = tmpmap["offset"].AsInteger() + start;
+ if (tmpmap.ContainsKey("size"))
+ physmesh_size = tmpmap["size"].AsInteger();
+
+ if (submesh_offset >= 0 || physmesh_size > 0)
+ {
+
+ if (!submesh(data, submesh_offset, physmesh_size, out phys_ntriangles))
+ {
+ error = "Model data parsing error";
+ return false;
+ }
+ }
+ }
+
+ // upload is done in convex shape type so only one hull
+ phys_hullsvertices++;
+ cost.physicsCost = 0.04f * phys_hullsvertices;
+
+ float sfee;
+
+ sfee = data.Length; // start with total compressed data size
+
+ // penalize lod meshs that should be more builder optimized
+ sfee += medSizeWth * medlod_size;
+ sfee += lowSizeWth * lowlod_size;
+ sfee += lowestSizeWth * lowlod_size;
+
+ // physics
+ // favor potencial optimized meshs versus automatic decomposition
+ if (physmesh_size != 0)
+ sfee += physMeshSizeWth * (physmesh_size + hulls_size / 4); // reduce cost of mandatory convex hull
+ else
+ sfee += physHullSizeWth * hulls_size;
+
+ // bytes to money
+ sfee *= bytecost;
+
+ cost.costFee = sfee;
+ return true;
+ }
+
+ // parses a LOD or physics mesh component
+ private bool submesh(byte[] data, int offset, int size, out int ntriangles)
+ {
+ ntriangles = 0;
+
+ OSD decodedMeshOsd = new OSD();
+ byte[] meshBytes = new byte[size];
+ System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
+ try
+ {
+ using (MemoryStream inMs = new MemoryStream(meshBytes))
+ {
+ using (MemoryStream outMs = new MemoryStream())
+ {
+ using (ZOutputStream zOut = new ZOutputStream(outMs))
+ {
+ byte[] readBuffer = new byte[4096];
+ int readLen = 0;
+ while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
+ {
+ zOut.Write(readBuffer, 0, readLen);
+ }
+ zOut.Flush();
+ outMs.Seek(0, SeekOrigin.Begin);
+
+ byte[] decompressedBuf = outMs.GetBuffer();
+ decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ OSDArray decodedMeshOsdArray = null;
+ if ((!decodedMeshOsd is OSDArray))
+ return false;
+
+ byte[] dummy;
+
+ decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
+ foreach (OSD subMeshOsd in decodedMeshOsdArray)
+ {
+ if (subMeshOsd is OSDMap)
+ {
+ OSDMap subtmpmap = (OSDMap)subMeshOsd;
+ if (subtmpmap.ContainsKey("NoGeometry") && ((OSDBoolean)subtmpmap["NoGeometry"]))
+ continue;
+
+ if (!subtmpmap.ContainsKey("Position"))
+ return false;
+
+ if (subtmpmap.ContainsKey("TriangleList"))
+ {
+ dummy = subtmpmap["TriangleList"].AsBinary();
+ ntriangles += dummy.Length / bytesPerCoord;
+ }
+ else
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // parses convex hulls component
+ private bool hulls(byte[] data, int offset, int size, out int nvertices, out int nhulls)
+ {
+ nvertices = 0;
+ nhulls = 1;
+
+ OSD decodedMeshOsd = new OSD();
+ byte[] meshBytes = new byte[size];
+ System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
+ try
+ {
+ using (MemoryStream inMs = new MemoryStream(meshBytes))
+ {
+ using (MemoryStream outMs = new MemoryStream())
+ {
+ using (ZOutputStream zOut = new ZOutputStream(outMs))
+ {
+ byte[] readBuffer = new byte[4096];
+ int readLen = 0;
+ while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
+ {
+ zOut.Write(readBuffer, 0, readLen);
+ }
+ zOut.Flush();
+ outMs.Seek(0, SeekOrigin.Begin);
+
+ byte[] decompressedBuf = outMs.GetBuffer();
+ decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ OSDMap cmap = (OSDMap)decodedMeshOsd;
+ if (cmap == null)
+ return false;
+
+ byte[] dummy;
+
+ // must have one of this
+ if (cmap.ContainsKey("BoundingVerts"))
+ {
+ dummy = cmap["BoundingVerts"].AsBinary();
+ nvertices = dummy.Length / bytesPerCoord;
+ }
+ else
+ return false;
+
+/* upload is done with convex shape type
+ if (cmap.ContainsKey("HullList"))
+ {
+ dummy = cmap["HullList"].AsBinary();
+ nhulls += dummy.Length;
+ }
+
+
+ if (cmap.ContainsKey("Positions"))
+ {
+ dummy = cmap["Positions"].AsBinary();
+ nvertices = dummy.Length / bytesPerCoord;
+ }
+ */
+
+ return true;
+ }
+
+ // returns streaming cost from on mesh LODs sizes in curCost and square of prim size length
+ private float streamingCost(ameshCostParam curCost, float sqdiam)
+ {
+ // compute efective areas
+ float ma = 262144f;
+
+ float mh = sqdiam * highLodFactor;
+ if (mh > ma)
+ mh = ma;
+ float mm = sqdiam * midLodFactor;
+ if (mm > ma)
+ mm = ma;
+
+ float ml = sqdiam * lowLodFactor;
+ if (ml > ma)
+ ml = ma;
+
+ float mlst = ma;
+
+ mlst -= ml;
+ ml -= mm;
+ mm -= mh;
+
+ if (mlst < 1.0f)
+ mlst = 1.0f;
+ if (ml < 1.0f)
+ ml = 1.0f;
+ if (mm < 1.0f)
+ mm = 1.0f;
+ if (mh < 1.0f)
+ mh = 1.0f;
+
+ ma = mlst + ml + mm + mh;
+
+ // get LODs compressed sizes
+ // giving 384 bytes bonus
+ int lst = curCost.lowestLODSize - 384;
+ int l = curCost.lowLODSize - 384;
+ int m = curCost.medLODSize - 384;
+ int h = curCost.highLODSize - 384;
+
+ // use previus higher LOD size on missing ones
+ if (m <= 0)
+ m = h;
+ if (l <= 0)
+ l = m;
+ if (lst <= 0)
+ lst = l;
+
+ // force minumum sizes
+ if (lst < 16)
+ lst = 16;
+ if (l < 16)
+ l = 16;
+ if (m < 16)
+ m = 16;
+ if (h < 16)
+ h = 16;
+
+ // compute cost weighted by relative effective areas
+ float cost = (float)lst * mlst + (float)l * ml + (float)m * mm + (float)h * mh;
+ cost /= ma;
+
+ cost *= 0.004f; // overall tunning parameter
+
+ return cost;
+ }
+ }
+}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index ebfe68721e..e113c60fd1 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -419,7 +419,7 @@ namespace OpenSim.Region.ClientStack.Linden
}
}
- public Hashtable GetEvents(UUID requestID, UUID pAgentId, string request)
+ public Hashtable GetEvents(UUID requestID, UUID pAgentId)
{
if (DebugLevel >= 2)
m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index 5b125eac75..cc65981200 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -53,6 +53,14 @@ namespace OpenSim.Region.ClientStack.Linden
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")]
public class GetTextureModule : INonSharedRegionModule
{
+
+ struct aPollRequest
+ {
+ public PollServiceTextureEventArgs thepoll;
+ public UUID reqID;
+ public Hashtable request;
+ }
+
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene;
@@ -64,8 +72,8 @@ namespace OpenSim.Region.ClientStack.Linden
private Dictionary m_capsDict = new Dictionary();
private static Thread[] m_workerThreads = null;
- private static OpenMetaverse.BlockingQueue m_queue =
- new OpenMetaverse.BlockingQueue();
+ private static OpenMetaverse.BlockingQueue m_queue =
+ new OpenMetaverse.BlockingQueue();
#region ISharedRegionModule Members
@@ -104,7 +112,7 @@ namespace OpenSim.Region.ClientStack.Linden
String.Format("TextureWorkerThread{0}", i),
ThreadPriority.Normal,
false,
- true,
+ false,
null,
int.MaxValue);
}
@@ -129,7 +137,8 @@ namespace OpenSim.Region.ClientStack.Linden
~GetTextureModule()
{
foreach (Thread t in m_workerThreads)
- t.Abort();
+ Watchdog.AbortThread(t.ManagedThreadId);
+
}
private class PollServiceTextureEventArgs : PollServiceEventArgs
@@ -142,40 +151,50 @@ namespace OpenSim.Region.ClientStack.Linden
private Scene m_scene;
public PollServiceTextureEventArgs(UUID pId, Scene scene) :
- base(null, null, null, null, pId, 30000)
+ base(null, null, null, null, pId, int.MaxValue)
{
m_scene = scene;
- HasEvents = (x, y) => { return this.responses.ContainsKey(x); };
- GetEvents = (x, y, s) =>
+ HasEvents = (x, y) =>
{
- try
+ lock (responses)
+ return responses.ContainsKey(x);
+ };
+ GetEvents = (x, y) =>
+ {
+ lock (responses)
{
- return this.responses[x];
- }
- finally
- {
- responses.Remove(x);
+ try
+ {
+ return responses[x];
+ }
+ finally
+ {
+ responses.Remove(x);
+ }
}
};
Request = (x, y) =>
{
- y["RequestID"] = x.ToString();
- lock (this.requests)
- this.requests.Add(y);
+ aPollRequest reqinfo = new aPollRequest();
+ reqinfo.thepoll = this;
+ reqinfo.reqID = x;
+ reqinfo.request = y;
- m_queue.Enqueue(this);
+ m_queue.Enqueue(reqinfo);
};
+ // this should never happen except possible on shutdown
NoEvents = (x, y) =>
{
- lock (this.requests)
+/*
+ lock (requests)
{
Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
requests.Remove(request);
}
-
+*/
Hashtable response = new Hashtable();
response["int_response_code"] = 500;
@@ -188,25 +207,11 @@ namespace OpenSim.Region.ClientStack.Linden
};
}
- public void Process()
+ public void Process(aPollRequest requestinfo)
{
Hashtable response;
- Hashtable request = null;
- try
- {
- lock (this.requests)
- {
- request = requests[0];
- requests.RemoveAt(0);
- }
- }
- catch
- {
- return;
- }
-
- UUID requestID = new UUID(request["RequestID"].ToString());
+ UUID requestID = requestinfo.reqID;
// If the avatar is gone, don't bother to get the texture
if (m_scene.GetScenePresence(Id) == null)
@@ -219,13 +224,15 @@ namespace OpenSim.Region.ClientStack.Linden
response["keepalive"] = false;
response["reusecontext"] = false;
- responses[requestID] = response;
+ lock (responses)
+ responses[requestID] = response;
+
return;
}
- response = m_getTextureHandler.Handle(request);
-
- responses[requestID] = response;
+ response = m_getTextureHandler.Handle(requestinfo.request);
+ lock (responses)
+ responses[requestID] = response;
}
}
@@ -233,8 +240,7 @@ namespace OpenSim.Region.ClientStack.Linden
{
string capUrl = "/CAPS/" + UUID.Random() + "/";
- // Register this as a poll service
- // absurd large timeout to tune later to make a bit less than viewer
+ // Register this as a poll service
PollServiceTextureEventArgs args = new PollServiceTextureEventArgs(agentID, m_scene);
args.Type = PollServiceEventArgs.EventType.Texture;
@@ -270,11 +276,10 @@ namespace OpenSim.Region.ClientStack.Linden
{
while (true)
{
- PollServiceTextureEventArgs args = m_queue.Dequeue();
+ aPollRequest poolreq = m_queue.Dequeue();
- args.Process();
+ poolreq.thepoll.Process(poolreq);
}
}
}
-
}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
index 44a68839ca..0251ac4d99 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
@@ -129,15 +129,15 @@ namespace OpenSim.Region.ClientStack.Linden
// m_log.DebugFormat("[MESH UPLOAD FLAG MODULE]: MeshUploadFlag request");
OSDMap data = new OSDMap();
- ScenePresence sp = m_scene.GetScenePresence(m_agentID);
- data["username"] = sp.Firstname + "." + sp.Lastname;
- data["display_name_next_update"] = new OSDDate(DateTime.Now);
- data["legacy_first_name"] = sp.Firstname;
+// ScenePresence sp = m_scene.GetScenePresence(m_agentID);
+// data["username"] = sp.Firstname + "." + sp.Lastname;
+// data["display_name_next_update"] = new OSDDate(DateTime.Now);
+// data["legacy_first_name"] = sp.Firstname;
data["mesh_upload_status"] = "valid";
- data["display_name"] = sp.Firstname + " " + sp.Lastname;
- data["legacy_last_name"] = sp.Lastname;
- data["id"] = m_agentID;
- data["is_display_name_default"] = true;
+// data["display_name"] = sp.Firstname + " " + sp.Lastname;
+// data["legacy_last_name"] = sp.Lastname;
+// data["id"] = m_agentID;
+// data["is_display_name_default"] = true;
//Send back data
Hashtable responsedata = new Hashtable();
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 4908c2c7e1..0caeddf2b2 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -52,6 +52,13 @@ namespace OpenSim.Region.ClientStack.Linden
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
public class WebFetchInvDescModule : INonSharedRegionModule
{
+ struct aPollRequest
+ {
+ public PollServiceInventoryEventArgs thepoll;
+ public UUID reqID;
+ public Hashtable request;
+ }
+
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene;
@@ -64,8 +71,8 @@ namespace OpenSim.Region.ClientStack.Linden
private Dictionary m_capsDict = new Dictionary();
private static Thread[] m_workerThreads = null;
- private static OpenMetaverse.BlockingQueue m_queue =
- new OpenMetaverse.BlockingQueue();
+ private static OpenMetaverse.BlockingQueue m_queue =
+ new OpenMetaverse.BlockingQueue();
#region ISharedRegionModule Members
@@ -131,49 +138,52 @@ namespace OpenSim.Region.ClientStack.Linden
~WebFetchInvDescModule()
{
foreach (Thread t in m_workerThreads)
- t.Abort();
+ Watchdog.AbortThread(t.ManagedThreadId);
}
private class PollServiceInventoryEventArgs : PollServiceEventArgs
{
- private List requests =
- new List();
private Dictionary responses =
new Dictionary();
public PollServiceInventoryEventArgs(UUID pId) :
- base(null, null, null, null, pId, 30000)
+ base(null, null, null, null, pId, int.MaxValue)
{
- HasEvents = (x, y) => { return this.responses.ContainsKey(x); };
- GetEvents = (x, y, s) =>
+ HasEvents = (x, y) => { lock (responses) return responses.ContainsKey(x); };
+ GetEvents = (x, y) =>
{
- try
+ lock (responses)
{
- return this.responses[x];
- }
- finally
- {
- responses.Remove(x);
+ try
+ {
+ return responses[x];
+ }
+ finally
+ {
+ responses.Remove(x);
+ }
}
};
Request = (x, y) =>
{
- y["RequestID"] = x.ToString();
- lock (this.requests)
- this.requests.Add(y);
+ aPollRequest reqinfo = new aPollRequest();
+ reqinfo.thepoll = this;
+ reqinfo.reqID = x;
+ reqinfo.request = y;
- m_queue.Enqueue(this);
+ m_queue.Enqueue(reqinfo);
};
NoEvents = (x, y) =>
{
- lock (this.requests)
+/*
+ lock (requests)
{
Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
requests.Remove(request);
}
-
+*/
Hashtable response = new Hashtable();
response["int_response_code"] = 500;
@@ -186,24 +196,9 @@ namespace OpenSim.Region.ClientStack.Linden
};
}
- public void Process()
+ public void Process(aPollRequest requestinfo)
{
- Hashtable request = null;
-
- try
- {
- lock (this.requests)
- {
- request = requests[0];
- requests.RemoveAt(0);
- }
- }
- catch
- {
- return;
- }
-
- UUID requestID = new UUID(request["RequestID"].ToString());
+ UUID requestID = requestinfo.reqID;
Hashtable response = new Hashtable();
@@ -212,9 +207,11 @@ namespace OpenSim.Region.ClientStack.Linden
response["keepalive"] = false;
response["reusecontext"] = false;
- response["str_response_string"] = m_webFetchHandler.FetchInventoryDescendentsRequest(request["body"].ToString(), String.Empty, String.Empty, null, null);
+ response["str_response_string"] = m_webFetchHandler.FetchInventoryDescendentsRequest(
+ requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
- responses[requestID] = response;
+ lock (responses)
+ responses[requestID] = response;
}
}
@@ -222,8 +219,7 @@ namespace OpenSim.Region.ClientStack.Linden
{
string capUrl = "/CAPS/" + UUID.Random() + "/";
- // Register this as a poll service
- // absurd large timeout to tune later to make a bit less than viewer
+ // Register this as a poll service
PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(agentID);
args.Type = PollServiceEventArgs.EventType.Inventory;
@@ -259,9 +255,9 @@ namespace OpenSim.Region.ClientStack.Linden
{
while (true)
{
- PollServiceInventoryEventArgs args = m_queue.Dequeue();
+ aPollRequest poolreq = m_queue.Dequeue();
- args.Process();
+ poolreq.thepoll.Process(poolreq);
}
}
}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 74b27d7bf4..6f00957743 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -2066,8 +2066,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
}
- /// IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)
public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
+ {
+ SendInventoryItemCreateUpdate(Item, UUID.Zero, callbackId);
+ }
+
+ /// IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)
+ public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
{
const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
@@ -2078,6 +2083,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// TODO: don't create new blocks if recycling an old packet
InventoryReply.AgentData.AgentID = AgentId;
InventoryReply.AgentData.SimApproved = true;
+ InventoryReply.AgentData.TransactionID = transactionID;
InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
InventoryReply.InventoryData[0].ItemID = Item.ID;
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index 0271738aee..da1ff2ecbb 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -143,7 +143,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
}
}
- public void RequestCreateInventoryItem(IClientAPI remoteClient,
+ public bool RequestCreateInventoryItem(IClientAPI remoteClient,
UUID transactionID, UUID folderID, uint callbackID,
string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask)
@@ -153,6 +153,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
uploader.RequestCreateInventoryItem(
remoteClient, folderID, callbackID,
description, name, invType, type, wearableType, nextOwnerMask);
+
+ return true;
}
public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient,
@@ -172,4 +174,4 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
uploader.RequestUpdateInventoryItem(remoteClient, item);
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
index 73d1f72b2a..4bb8986e08 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -158,7 +158,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
///
///
///
- public void HandleItemCreationFromTransaction(IClientAPI remoteClient,
+ public bool HandleItemCreationFromTransaction(IClientAPI remoteClient,
UUID transactionID, UUID folderID, uint callbackID,
string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask)
@@ -169,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
AgentAssetTransactions transactions =
GetUserTransactions(remoteClient.AgentId);
- transactions.RequestCreateInventoryItem(remoteClient, transactionID,
+ return transactions.RequestCreateInventoryItem(remoteClient, transactionID,
folderID, callbackID, description, name, invType, type,
wearableType, nextOwnerMask);
}
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 1492302f54..716cc69736 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -256,7 +256,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
if (sp.IsChildAgent)
return;
sp.ControllingClient.Kick(reason);
- sp.Scene.IncomingCloseAgent(sp.UUID);
+ sp.MakeChildAgent();
+ sp.ControllingClient.Close();
}
private void OnIncomingInstantMessage(GridInstantMessage msg)
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 1f62743b31..c5bb9a5080 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -663,7 +663,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
//
// This sleep can be increased if necessary. However, whilst it's active,
// an agent cannot teleport back to this region if it has teleported away.
- Thread.Sleep(2000);
+ Thread.Sleep(3000);
sp.Scene.IncomingCloseAgent(sp.UUID, false);
}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 9a56f42567..50f5f68ab9 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -186,45 +186,44 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
if (folder == null || folder.Owner != remoteClient.AgentId)
return;
- if (transactionID == UUID.Zero)
- {
- ScenePresence presence;
- if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence))
- {
- byte[] data = null;
-
- if (invType == (sbyte)InventoryType.Landmark && presence != null)
- {
- string suffix = string.Empty, prefix = string.Empty;
- string strdata = GenerateLandmark(presence, out prefix, out suffix);
- data = Encoding.ASCII.GetBytes(strdata);
- name = prefix + name;
- description += suffix;
- }
-
- AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
- m_Scene.AssetService.Store(asset);
- m_Scene.CreateNewInventoryItem(
- remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
- name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate);
- }
- else
- {
- m_log.ErrorFormat(
- "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
- remoteClient.AgentId);
- }
- }
- else
+ if (transactionID != UUID.Zero)
{
IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule;
if (agentTransactions != null)
{
- agentTransactions.HandleItemCreationFromTransaction(
+ if (agentTransactions.HandleItemCreationFromTransaction(
remoteClient, transactionID, folderID, callbackID, description,
- name, invType, assetType, wearableType, nextOwnerMask);
+ name, invType, assetType, wearableType, nextOwnerMask))
+ return;
}
}
+
+ ScenePresence presence;
+ if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence))
+ {
+ byte[] data = null;
+
+ if (invType == (sbyte)InventoryType.Landmark && presence != null)
+ {
+ string suffix = string.Empty, prefix = string.Empty;
+ string strdata = GenerateLandmark(presence, out prefix, out suffix);
+ data = Encoding.ASCII.GetBytes(strdata);
+ name = prefix + name;
+ description += suffix;
+ }
+
+ AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
+ m_Scene.AssetService.Store(asset);
+ m_Scene.CreateNewInventoryItem(
+ remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
+ name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate,transactionID);
+ }
+ else
+ {
+ m_log.ErrorFormat(
+ "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
+ remoteClient.AgentId);
+ }
}
protected virtual string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix)
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 99ffbe7c50..0b9174f799 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -461,7 +461,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
}
}
}
- private Hashtable GetEvents(UUID requestID, UUID sessionID, string request)
+ private Hashtable GetEvents(UUID requestID, UUID sessionID)
{
UrlData url = null;
RequestData requestData = null;
diff --git a/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs b/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
index 0cc8fb6acd..e0aad2b1d8 100644
--- a/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.Framework.Interfaces
void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID,
InventoryItemBase item);
- void HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID,
+ bool HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID,
uint callbackID, string description, string name, sbyte invType,
sbyte type, byte wearableType, uint nextOwnerMask);
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 3d68081e79..35df85c750 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -904,11 +904,22 @@ namespace OpenSim.Region.Framework.Scenes
public void CreateNewInventoryItem(
IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
string name, string description, uint flags, uint callbackID,
- AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate)
+ AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate, UUID transationID)
{
CreateNewInventoryItem(
remoteClient, creatorID, creatorData, folderID, name, description, flags, callbackID, asset, invType,
- (uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate);
+ (uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate, transationID);
+ }
+
+
+ private void CreateNewInventoryItem(
+ IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
+ string name, string description, uint flags, uint callbackID, AssetBase asset, sbyte invType,
+ uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate)
+ {
+ CreateNewInventoryItem(remoteClient, creatorID, creatorData, folderID,
+ name, description, flags, callbackID, asset, invType,
+ baseMask, currentMask, everyoneMask, nextOwnerMask, groupMask, creationDate, UUID.Zero);
}
///
@@ -933,7 +944,7 @@ namespace OpenSim.Region.Framework.Scenes
private void CreateNewInventoryItem(
IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
string name, string description, uint flags, uint callbackID, AssetBase asset, sbyte invType,
- uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate)
+ uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate,UUID transationID)
{
InventoryItemBase item = new InventoryItemBase();
item.Owner = remoteClient.AgentId;
@@ -956,7 +967,7 @@ namespace OpenSim.Region.Framework.Scenes
if (AddInventoryItem(item))
{
- remoteClient.SendInventoryItemCreateUpdate(item, callbackID);
+ remoteClient.SendInventoryItemCreateUpdate(item, transationID, callbackID);
}
else
{
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 129bf090d3..29c8eb16cd 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -4372,7 +4372,7 @@ namespace OpenSim.Region.Framework.Scenes
ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
if (presence != null)
{
- presence.ControllingClient.Close(true, force);
+ presence.ControllingClient.Close(force, force);
return true;
}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 44573eb746..a31a9ea173 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -2146,10 +2146,10 @@ namespace OpenSim.Region.Framework.Scenes
{
if (asset != null)
SculptTextureCallback(asset);
- else
- m_log.WarnFormat(
- "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
- Name, UUID, id);
+// else
+// m_log.WarnFormat(
+// "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
+// Name, UUID, id);
}
///
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 1660c45d30..f3382b2081 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -1100,7 +1100,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
{
-
+
+ }
+
+ public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
+ {
+
}
public void SendRemoveInventoryItem(UUID itemID)
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 625342e257..bb3748ec29 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -739,6 +739,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
+ public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
+ {
+ }
+
public virtual void SendRemoveInventoryItem(UUID itemID)
{
}
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
index fbc61342af..61d5a1d8e4 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
@@ -902,7 +902,7 @@ namespace OpenSim.Region.Physics.OdePlugin
axis.X = (axis.X > 0) ? 1f : 0f;
axis.Y = (axis.Y > 0) ? 1f : 0f;
axis.Z = (axis.Z > 0) ? 1f : 0f;
- m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
+// m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
AddChange(changes.AngLock, axis);
}
else
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 8d06d833f0..f0d378ddff 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -10149,31 +10149,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
UUID key = new UUID();
if (UUID.TryParse(id, out key))
{
- try
- {
- /*
- SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
- if (obj != null)
- return (double)obj.GetMass();
- */
- // return total object mass
- SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId);
- if (obj != null)
- return obj.GetMass();
+ // return total object mass
+ SceneObjectPart part = World.GetSceneObjectPart(key);
+ if (part != null)
+ return part.ParentGroup.GetMass();
- // the object is null so the key is for an avatar
- ScenePresence avatar = World.GetScenePresence(key);
- if (avatar != null)
- if (avatar.IsChildAgent)
- // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
- // child agents have a mass of 1.0
- return 1;
- else
- return (double)avatar.GetMass();
- }
- catch (KeyNotFoundException)
+ // the object is null so the key is for an avatar
+ ScenePresence avatar = World.GetScenePresence(key);
+ if (avatar != null)
{
- return 0; // The Object/Agent not in the region so just return zero
+ if (avatar.IsChildAgent)
+ {
+ // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
+ // child agents have a mass of 1.0
+ return 1;
+ }
+ else
+ {
+ return (double)avatar.GetMass();
+ }
}
}
return 0;
diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
index d772c391ac..0bd8269acc 100644
--- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
@@ -443,7 +443,15 @@ namespace OpenSim.Server.Handlers.Simulation
// subclasses can override this
protected virtual bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason)
{
- return m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason);
+ reason = String.Empty;
+
+ Util.FireAndForget(x =>
+ {
+ string r;
+ m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out r);
+ });
+
+ return true;
}
}
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
index daf38bc1cd..9d6d9ad69c 100644
--- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
@@ -27,6 +27,7 @@
using log4net;
using System;
+using System.Threading;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
@@ -50,7 +51,7 @@ namespace OpenSim.Services.Connectors
private IImprovedAssetCache m_Cache = null;
private int m_retryCounter;
private Dictionary> m_retryQueue = new Dictionary>();
- private Timer m_retryTimer;
+ private System.Timers.Timer m_retryTimer;
private delegate void AssetRetrievedEx(AssetBase asset);
// Keeps track of concurrent requests for the same asset, so that it's only loaded once.
@@ -61,6 +62,8 @@ namespace OpenSim.Services.Connectors
private Dictionary m_UriMap = new Dictionary();
+ private Thread[] m_fetchThreads;
+
public AssetServicesConnector()
{
}
@@ -96,7 +99,7 @@ namespace OpenSim.Services.Connectors
}
- m_retryTimer = new Timer();
+ m_retryTimer = new System.Timers.Timer();
m_retryTimer.Elapsed += new ElapsedEventHandler(retryCheck);
m_retryTimer.Interval = 60000;
@@ -112,6 +115,14 @@ namespace OpenSim.Services.Connectors
m_UriMap[prefix] = groupHost;
//m_log.DebugFormat("[ASSET]: Using {0} for prefix {1}", groupHost, prefix);
}
+
+ m_fetchThreads = new Thread[2];
+
+ for (int i = 0 ; i < 2 ; i++)
+ {
+ m_fetchThreads[i] = new Thread(AssetRequestProcessor);
+ m_fetchThreads[i].Start();
+ }
}
private string MapServer(string id)
@@ -261,6 +272,66 @@ namespace OpenSim.Services.Connectors
return null;
}
+ private class QueuedAssetRequest
+ {
+ public string uri;
+ public string id;
+ }
+
+ private OpenMetaverse.BlockingQueue m_requestQueue =
+ new OpenMetaverse.BlockingQueue();
+
+ private void AssetRequestProcessor()
+ {
+ QueuedAssetRequest r;
+
+ while (true)
+ {
+ r = m_requestQueue.Dequeue();
+
+ string uri = r.uri;
+ string id = r.id;
+
+ bool success = false;
+ try
+ {
+ AsynchronousRestObjectRequester.MakeRequest("GET", uri, 0,
+ delegate(AssetBase a)
+ {
+ if (m_Cache != null)
+ m_Cache.Cache(a);
+
+ List handlers;
+ lock (m_AssetHandlers)
+ {
+ handlers = m_AssetHandlers[id];
+ m_AssetHandlers.Remove(id);
+ }
+ foreach (AssetRetrievedEx h in handlers)
+ h.Invoke(a);
+ if (handlers != null)
+ handlers.Clear();
+ }, 30);
+
+ success = true;
+ }
+ finally
+ {
+ if (!success)
+ {
+ List handlers;
+ lock (m_AssetHandlers)
+ {
+ handlers = m_AssetHandlers[id];
+ m_AssetHandlers.Remove(id);
+ }
+ if (handlers != null)
+ handlers.Clear();
+ }
+ }
+ }
+ }
+
public bool Get(string id, Object sender, AssetRetrieved handler)
{
string uri = MapServer(id) + "/assets/" + id;
@@ -293,52 +364,11 @@ namespace OpenSim.Services.Connectors
m_AssetHandlers.Add(id, handlers);
}
- bool success = false;
- try
- {
- AsynchronousRestObjectRequester.MakeRequest("GET", uri, 0,
- delegate(AssetBase a)
- {
- if (m_Cache != null)
- m_Cache.Cache(a);
-/*
- AssetRetrievedEx handlers;
- lock (m_AssetHandlers)
- {
- handlers = m_AssetHandlers[id];
- m_AssetHandlers.Remove(id);
- }
+ QueuedAssetRequest request = new QueuedAssetRequest();
+ request.id = id;
+ request.uri = uri;
- handlers.Invoke(a);
-*/
- List handlers;
- lock (m_AssetHandlers)
- {
- handlers = m_AssetHandlers[id];
- m_AssetHandlers.Remove(id);
- }
- foreach (AssetRetrievedEx h in handlers)
- h.Invoke(a);
- if (handlers != null)
- handlers.Clear();
- }, 30);
-
- success = true;
- }
- finally
- {
- if (!success)
- {
- List handlers;
- lock (m_AssetHandlers)
- {
- handlers = m_AssetHandlers[id];
- m_AssetHandlers.Remove(id);
- }
- if (handlers != null)
- handlers.Clear();
- }
- }
+ m_requestQueue.Enqueue(request);
}
else
{
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 4e3bc6738a..87ca944e67 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -716,6 +716,10 @@ namespace OpenSim.Tests.Common.Mock
{
}
+ public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
+ {
+ }
+
public virtual void SendRemoveInventoryItem(UUID itemID)
{
}
diff --git a/prebuild.xml b/prebuild.xml
index 4e12fe993f..d149010d06 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -162,6 +162,7 @@
+
@@ -1703,7 +1704,7 @@
-
+
@@ -1713,6 +1714,7 @@
+