Merge branch 'master' into httptests
commit
6d4b0a8ce3
|
@ -145,7 +145,12 @@
|
|||
</exec>
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.services.inventoryservice.tests)==0}" />
|
||||
|
||||
<delete dir="%temp%"/>
|
||||
<exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.permissions">
|
||||
<arg value="./bin/OpenSim.Tests.Permissions.dll" />
|
||||
</exec>
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests.permissions)==0}" />
|
||||
|
||||
<delete dir="%temp%"/>
|
||||
</target>
|
||||
|
||||
<target name="test-stress" depends="build, find-nunit">
|
||||
|
@ -260,6 +265,11 @@
|
|||
<arg value="-xml=test-results/OpenSim.Services.InventoryService.Tests.dll-Results.xml" />
|
||||
</exec>
|
||||
|
||||
<exec program="${nunitcmd}" failonerror="false" resultproperty="testresult.opensim.tests.permissions">
|
||||
<arg value="./bin/OpenSim.Tests.Permissions.dll" />
|
||||
<arg value="-xml=test-results/OpenSim.Tests.Permissions.dll-Results.xml" />
|
||||
</exec>
|
||||
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests)==0}" />
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.tests)==0}" />
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.framework.servers.tests)==0}" />
|
||||
|
@ -271,6 +281,7 @@
|
|||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.data.tests)==0}" />
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.capabilities.handlers.tests)==0}" />
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.services.inventoryservice.tests)==0}" />
|
||||
<fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests.permissions)==0}" />
|
||||
</target>
|
||||
|
||||
<target name="doxygen">
|
||||
|
|
|
@ -305,18 +305,12 @@ namespace OpenSim.Data.SQLite
|
|||
|
||||
using (SqliteCommand cmd = new SqliteCommand())
|
||||
{
|
||||
cmd.CommandText = "update inventoryfolders set version=version+1 where folderID = ?folderID";
|
||||
cmd.CommandText = "update inventoryfolders set version=version+1 where folderID = :folderID";
|
||||
cmd.Parameters.Add(new SqliteParameter(":folderID", folderID));
|
||||
|
||||
try
|
||||
{
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if(ExecuteNonQuery(cmd, m_Connection) == 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,8 @@ using OpenMetaverse;
|
|||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
public delegate bool AnimationSetValidator(UUID animID);
|
||||
// public delegate bool AnimationSetValidator(UUID animID);
|
||||
public delegate uint AnimationSetValidator(UUID animID);
|
||||
|
||||
public class AnimationSet
|
||||
{
|
||||
|
@ -141,7 +142,7 @@ namespace OpenSim.Framework
|
|||
assetData += String.Format("{0} {1} {2}\n", kvp.Key, kvp.Value.Value.ToString(), kvp.Value.Key);
|
||||
return System.Text.Encoding.ASCII.GetBytes(assetData);
|
||||
}
|
||||
|
||||
/*
|
||||
public bool Validate(AnimationSetValidator val)
|
||||
{
|
||||
if (m_parseError)
|
||||
|
@ -164,5 +165,22 @@ namespace OpenSim.Framework
|
|||
|
||||
return allOk;
|
||||
}
|
||||
*/
|
||||
public uint Validate(AnimationSetValidator val)
|
||||
{
|
||||
if (m_parseError)
|
||||
return 0;
|
||||
|
||||
uint ret = 0x7fffffff;
|
||||
uint t;
|
||||
foreach (KeyValuePair<string, KeyValuePair<string, UUID>> kvp in m_animations)
|
||||
{
|
||||
t = val(kvp.Value.Value);
|
||||
if (t == 0)
|
||||
return 0;
|
||||
ret &= t;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace OpenSim.Framework
|
|||
void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type, string extraData = "");
|
||||
void ApplyUploadCharge(UUID agentID, int amount, string text);
|
||||
void MoveMoney(UUID fromUser, UUID toUser, int amount, string text);
|
||||
bool MoveMoney(UUID fromUser, UUID toUser, int amount, MoneyTransactionType type, string text);
|
||||
|
||||
int UploadCharge { get; }
|
||||
int GroupCreationCharge { get; }
|
||||
|
|
|
@ -1970,7 +1970,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
|||
Hashtable headerdata = (Hashtable)responsedata["headers"];
|
||||
|
||||
foreach (string header in headerdata.Keys)
|
||||
response.AddHeader(header, (string)headerdata[header]);
|
||||
response.AddHeader(header, headerdata[header].ToString());
|
||||
}
|
||||
|
||||
byte[] buffer;
|
||||
|
|
|
@ -491,7 +491,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[INVENTORY]: Failed to process queued inventory request {0} for {1}. Exception {3}",
|
||||
"[INVENTORY]: Failed to process queued inventory request {0} for {1}. Exception {2}",
|
||||
poolreq.reqID, poolreq.presence != null ? poolreq.presence.Name : "unknown", e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6399,6 +6399,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
ParcelGodMarkAsContentPacket ParcelGodMarkAsContent =
|
||||
(ParcelGodMarkAsContentPacket)Packet;
|
||||
|
||||
if(SessionId != ParcelGodMarkAsContent.AgentData.SessionID || AgentId != ParcelGodMarkAsContent.AgentData.AgentID)
|
||||
return false;
|
||||
|
||||
ParcelGodMark ParcelGodMarkAsContentHandler = OnParcelGodMark;
|
||||
if (ParcelGodMarkAsContentHandler != null)
|
||||
{
|
||||
|
@ -6414,6 +6417,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
FreezeUserPacket FreezeUser = (FreezeUserPacket)Packet;
|
||||
|
||||
if(SessionId != FreezeUser.AgentData.SessionID || AgentId != FreezeUser.AgentData.AgentID)
|
||||
return false;
|
||||
|
||||
FreezeUserUpdate FreezeUserHandler = OnParcelFreezeUser;
|
||||
if (FreezeUserHandler != null)
|
||||
{
|
||||
|
@ -6431,6 +6437,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
EjectUserPacket EjectUser =
|
||||
(EjectUserPacket)Packet;
|
||||
|
||||
if(SessionId != EjectUser.AgentData.SessionID || AgentId != EjectUser.AgentData.AgentID)
|
||||
return false;
|
||||
|
||||
EjectUserUpdate EjectUserHandler = OnParcelEjectUser;
|
||||
if (EjectUserHandler != null)
|
||||
{
|
||||
|
@ -6448,6 +6457,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
ParcelBuyPassPacket ParcelBuyPass =
|
||||
(ParcelBuyPassPacket)Packet;
|
||||
|
||||
if(SessionId != ParcelBuyPass.AgentData.SessionID || AgentId != ParcelBuyPass.AgentData.AgentID)
|
||||
return false;
|
||||
|
||||
ParcelBuyPass ParcelBuyPassHandler = OnParcelBuyPass;
|
||||
if (ParcelBuyPassHandler != null)
|
||||
{
|
||||
|
|
|
@ -258,24 +258,24 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
|||
{
|
||||
m_uploadState = UploadState.Complete;
|
||||
|
||||
ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID);
|
||||
|
||||
bool sucess = true;
|
||||
if (m_createItem)
|
||||
{
|
||||
CompleteCreateItem(m_createItemCallback);
|
||||
sucess = CompleteCreateItem(m_createItemCallback);
|
||||
}
|
||||
else if (m_updateItem)
|
||||
{
|
||||
CompleteItemUpdate(m_updateItemData);
|
||||
sucess = CompleteItemUpdate(m_updateItemData);
|
||||
}
|
||||
else if (m_updateTaskItem)
|
||||
{
|
||||
CompleteTaskItemUpdate(m_updateTaskItemData);
|
||||
sucess = CompleteTaskItemUpdate(m_updateTaskItemData);
|
||||
}
|
||||
else if (m_asset.Local)
|
||||
{
|
||||
m_Scene.AssetService.Store(m_asset);
|
||||
}
|
||||
ourClient.SendAssetUploadCompleteMessage(m_asset.Type, sucess, m_asset.FullID);
|
||||
}
|
||||
|
||||
m_log.DebugFormat(
|
||||
|
@ -411,46 +411,70 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
|||
/// Store the asset for the given item when it has been uploaded.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
private void CompleteItemUpdate(InventoryItemBase item)
|
||||
private bool CompleteItemUpdate(InventoryItemBase item)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}",
|
||||
// m_asset.FullID, item.Name, ourClient.Name);
|
||||
|
||||
ValidateAssets();
|
||||
uint perms = ValidateAssets();
|
||||
if(perms == 0)
|
||||
{
|
||||
string error = string.Format("Not enough permissions on asset(s) referenced by item '{0}', update failed", item.Name);
|
||||
ourClient.SendAlertMessage(error);
|
||||
m_transactions.RemoveXferUploader(m_transactionID);
|
||||
ourClient.SendBulkUpdateInventory(item); // invalid the change item on viewer cache
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Scene.AssetService.Store(m_asset);
|
||||
if (m_asset.FullID != UUID.Zero)
|
||||
{
|
||||
item.AssetID = m_asset.FullID;
|
||||
m_Scene.InventoryService.UpdateItem(item);
|
||||
}
|
||||
|
||||
ourClient.SendInventoryItemCreateUpdate(item, m_transactionID, 0);
|
||||
|
||||
m_transactions.RemoveXferUploader(m_transactionID);
|
||||
|
||||
m_Scene.EventManager.TriggerOnNewInventoryItemUploadComplete(item, 0);
|
||||
}
|
||||
|
||||
return perms != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store the asset for the given task item when it has been uploaded.
|
||||
/// </summary>
|
||||
/// <param name="taskItem"></param>
|
||||
private void CompleteTaskItemUpdate(TaskInventoryItem taskItem)
|
||||
private bool CompleteTaskItemUpdate(TaskInventoryItem taskItem)
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}",
|
||||
// m_asset.FullID, taskItem.Name, ourClient.Name);
|
||||
|
||||
ValidateAssets();
|
||||
m_Scene.AssetService.Store(m_asset);
|
||||
|
||||
if(ValidateAssets() == 0)
|
||||
{
|
||||
m_transactions.RemoveXferUploader(m_transactionID);
|
||||
string error = string.Format("Not enough permissions on asset(s) referenced by task item '{0}', update failed", taskItem.Name);
|
||||
ourClient.SendAlertMessage(error);
|
||||
// force old asset to viewers ??
|
||||
return false;
|
||||
}
|
||||
|
||||
private void CompleteCreateItem(uint callbackID)
|
||||
m_Scene.AssetService.Store(m_asset);
|
||||
m_transactions.RemoveXferUploader(m_transactionID);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CompleteCreateItem(uint callbackID)
|
||||
{
|
||||
ValidateAssets();
|
||||
if(ValidateAssets() == 0)
|
||||
{
|
||||
m_transactions.RemoveXferUploader(m_transactionID);
|
||||
string error = string.Format("Not enough permissions on asset(s) referenced by item '{0}', creation failed", m_name);
|
||||
ourClient.SendAlertMessage(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Scene.AssetService.Store(m_asset);
|
||||
|
||||
InventoryItemBase item = new InventoryItemBase();
|
||||
|
@ -480,35 +504,40 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
|||
ourClient.SendAlertMessage("Unable to create inventory item");
|
||||
|
||||
m_transactions.RemoveXferUploader(m_transactionID);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void ValidateAssets()
|
||||
private uint ValidateAssets()
|
||||
{
|
||||
uint retPerms = 0x7fffffff;
|
||||
// if(m_Scene.Permissions.BypassPermissions())
|
||||
// return retPerms;
|
||||
|
||||
if (m_asset.Type == (sbyte)CustomAssetType.AnimationSet)
|
||||
{
|
||||
|
||||
AnimationSet animSet = new AnimationSet(m_asset.Data);
|
||||
|
||||
bool allOk = animSet.Validate(x => {
|
||||
int perms = m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, x);
|
||||
int required = (int)(PermissionMask.Transfer | PermissionMask.Copy);
|
||||
retPerms &= animSet.Validate(x => {
|
||||
const uint required = (uint)(PermissionMask.Transfer | PermissionMask.Copy);
|
||||
uint perms = (uint)m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, x);
|
||||
// currrent yes/no rule
|
||||
if ((perms & required) != required)
|
||||
return false;
|
||||
return true;
|
||||
return 0;
|
||||
return perms;
|
||||
});
|
||||
|
||||
if (!allOk)
|
||||
m_asset.Data = animSet.ToBytes();
|
||||
return retPerms;
|
||||
}
|
||||
|
||||
if (m_asset.Type == (sbyte)AssetType.Clothing ||
|
||||
m_asset.Type == (sbyte)AssetType.Bodypart)
|
||||
{
|
||||
const uint texturesfullPermMask = (uint)(PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Copy);
|
||||
string content = System.Text.Encoding.ASCII.GetString(m_asset.Data);
|
||||
string[] lines = content.Split(new char[] {'\n'});
|
||||
|
||||
List<string> validated = new List<string>();
|
||||
|
||||
// on current requiriment of full rigths assume old assets where accepted
|
||||
Dictionary<int, UUID> allowed = ExtractTexturesFromOldData();
|
||||
|
||||
int textures = 0;
|
||||
|
@ -518,10 +547,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
|||
try
|
||||
{
|
||||
if (line.StartsWith("textures "))
|
||||
{
|
||||
textures = Convert.ToInt32(line.Substring(9));
|
||||
validated.Add(line);
|
||||
}
|
||||
|
||||
else if (textures > 0)
|
||||
{
|
||||
string[] parts = line.Split(new char[] {' '});
|
||||
|
@ -532,42 +559,35 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
|||
if (defaultIDs.Contains(tx) || tx == UUID.Zero ||
|
||||
(allowed.ContainsKey(id) && allowed[id] == tx))
|
||||
{
|
||||
validated.Add(parts[0] + " " + tx.ToString());
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
int perms = m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, tx);
|
||||
int full = (int)(PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Copy);
|
||||
uint perms = (uint)m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, tx);
|
||||
|
||||
if ((perms & full) != full)
|
||||
if ((perms & texturesfullPermMask) != texturesfullPermMask)
|
||||
{
|
||||
m_log.ErrorFormat("[ASSET UPLOADER]: REJECTED update with texture {0} from {1} because they do not own the texture", tx, ourClient.AgentId);
|
||||
validated.Add(parts[0] + " " + UUID.Zero.ToString());
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
validated.Add(line);
|
||||
retPerms &= perms;
|
||||
}
|
||||
}
|
||||
textures--;
|
||||
}
|
||||
else
|
||||
{
|
||||
validated.Add(line);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// If it's malformed, skip it
|
||||
}
|
||||
}
|
||||
|
||||
string final = String.Join("\n", validated.ToArray());
|
||||
|
||||
m_asset.Data = System.Text.Encoding.ASCII.GetBytes(final);
|
||||
}
|
||||
return retPerms;
|
||||
}
|
||||
|
||||
/* not in use
|
||||
/// <summary>
|
||||
/// Get the asset data uploaded in this transfer.
|
||||
/// </summary>
|
||||
|
@ -582,7 +602,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
*/
|
||||
public void SetOldData(byte[] d)
|
||||
{
|
||||
m_oldData = d;
|
||||
|
|
|
@ -299,15 +299,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
|||
else if ((CustomInventoryType)item.InvType == CustomInventoryType.AnimationSet)
|
||||
{
|
||||
AnimationSet animSet = new AnimationSet(data);
|
||||
if (!animSet.Validate(x => {
|
||||
uint res = animSet.Validate(x => {
|
||||
const int required = (int)(PermissionMask.Transfer | PermissionMask.Copy);
|
||||
int perms = m_Scene.InventoryService.GetAssetPermissions(remoteClient.AgentId, x);
|
||||
int required = (int)(PermissionMask.Transfer | PermissionMask.Copy);
|
||||
// enforce previus perm rule
|
||||
if ((perms & required) != required)
|
||||
return false;
|
||||
return true;
|
||||
}))
|
||||
return 0;
|
||||
return (uint) perms;
|
||||
});
|
||||
if(res == 0)
|
||||
{
|
||||
data = animSet.ToBytes();
|
||||
remoteClient.SendAgentAlertMessage("Not enought permissions on asset(s) referenced by animation set '{0}', update failed", false);
|
||||
return UUID.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -250,6 +250,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
|||
if (inventoryURL != null && inventoryURL != string.Empty)
|
||||
{
|
||||
inventoryURL = inventoryURL.Trim(new char[] { '/' });
|
||||
lock (m_InventoryURLs)
|
||||
m_InventoryURLs[userID] = inventoryURL;
|
||||
m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Added {0} to the cache of inventory URLs", inventoryURL);
|
||||
return;
|
||||
|
@ -268,18 +269,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
|||
if (!string.IsNullOrEmpty(inventoryURL))
|
||||
{
|
||||
inventoryURL = inventoryURL.Trim(new char[] { '/' });
|
||||
m_InventoryURLs.Add(userID, inventoryURL);
|
||||
lock (m_InventoryURLs)
|
||||
m_InventoryURLs[userID] = inventoryURL;
|
||||
m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Added {0} to the cache of inventory URLs", inventoryURL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void DropInventoryServiceURL(UUID userID)
|
||||
{
|
||||
lock (m_InventoryURLs)
|
||||
{
|
||||
if (m_InventoryURLs.ContainsKey(userID))
|
||||
{
|
||||
string url = m_InventoryURLs[userID];
|
||||
|
@ -287,16 +288,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
|
|||
m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Removed {0} from the cache of inventory URLs", url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string GetInventoryServiceURL(UUID userID)
|
||||
{
|
||||
lock (m_InventoryURLs)
|
||||
{
|
||||
if (m_InventoryURLs.ContainsKey(userID))
|
||||
return m_InventoryURLs[userID];
|
||||
}
|
||||
|
||||
CacheInventoryServiceURL(userID);
|
||||
|
||||
lock (m_InventoryURLs)
|
||||
{
|
||||
if (m_InventoryURLs.ContainsKey(userID))
|
||||
return m_InventoryURLs[userID];
|
||||
}
|
||||
|
||||
return null; //it means that the methods should forward to local grid's inventory
|
||||
|
||||
|
|
|
@ -285,6 +285,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
|||
/// Dearchive the region embodied in this request.
|
||||
/// </summary>
|
||||
public void DearchiveRegion()
|
||||
{
|
||||
DearchiveRegion(true);
|
||||
}
|
||||
|
||||
public void DearchiveRegion(bool shouldStartScripts)
|
||||
{
|
||||
int successfulAssetRestores = 0;
|
||||
int failedAssetRestores = 0;
|
||||
|
@ -425,6 +430,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
|||
// Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so
|
||||
// that users can enter the scene. If we allow the scripts to start in the loop above
|
||||
// then they significantly increase the time until the OAR finishes loading.
|
||||
if (shouldStartScripts)
|
||||
{
|
||||
WorkManager.RunInThread(o =>
|
||||
{
|
||||
Thread.Sleep(15000);
|
||||
|
@ -441,6 +448,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
|||
sceneContext.SceneObjects.Clear();
|
||||
}
|
||||
}, null, string.Format("ReadArchiveStartScripts (request {0})", m_requestId));
|
||||
}
|
||||
|
||||
m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ using OpenSim.Framework;
|
|||
using OpenSim.Framework.Capabilities;
|
||||
using OpenSim.Framework.Console;
|
||||
using OpenSim.Framework.Servers;
|
||||
using OpenSim.Framework.Monitoring;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
|
@ -216,6 +217,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
client.OnParcelEjectUser += ClientOnParcelEjectUser;
|
||||
client.OnParcelFreezeUser += ClientOnParcelFreezeUser;
|
||||
client.OnSetStartLocationRequest += ClientOnSetHome;
|
||||
client.OnParcelBuyPass += ClientParcelBuyPass;
|
||||
}
|
||||
|
||||
public void EventMakeChildAgent(ScenePresence avatar)
|
||||
|
@ -537,6 +539,118 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
}
|
||||
}
|
||||
|
||||
public void ClientParcelBuyPass(IClientAPI remote_client, UUID targetID, int landLocalID)
|
||||
{
|
||||
ILandObject land;
|
||||
lock (m_landList)
|
||||
{
|
||||
m_landList.TryGetValue(landLocalID, out land);
|
||||
}
|
||||
// trivial checks
|
||||
if(land == null)
|
||||
return;
|
||||
|
||||
LandData ldata = land.LandData;
|
||||
|
||||
if(ldata == null)
|
||||
return;
|
||||
|
||||
if(ldata.OwnerID == targetID)
|
||||
return;
|
||||
|
||||
if(ldata.PassHours == 0)
|
||||
return;
|
||||
|
||||
// don't allow passes on group owned until we can give money to groups
|
||||
if(ldata.IsGroupOwned)
|
||||
{
|
||||
remote_client.SendAgentAlertMessage("pass to group owned parcel not suported", false);
|
||||
return;
|
||||
}
|
||||
|
||||
if((ldata.Flags & (uint)ParcelFlags.UsePassList) == 0)
|
||||
return;
|
||||
|
||||
int cost = ldata.PassPrice;
|
||||
|
||||
int idx = land.LandData.ParcelAccessList.FindIndex(
|
||||
delegate(LandAccessEntry e)
|
||||
{
|
||||
if (e.AgentID == targetID && e.Flags == AccessList.Access)
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
int now = Util.UnixTimeSinceEpoch();
|
||||
int expires = (int)(3600.0 * ldata.PassHours + 0.5f);
|
||||
int currenttime = -1;
|
||||
if (idx != -1)
|
||||
{
|
||||
if(ldata.ParcelAccessList[idx].Expires == 0)
|
||||
{
|
||||
remote_client.SendAgentAlertMessage("You already have access to parcel", false);
|
||||
return;
|
||||
}
|
||||
|
||||
currenttime = ldata.ParcelAccessList[idx].Expires - now;
|
||||
if(currenttime > (int)(0.25f * expires + 0.5f))
|
||||
{
|
||||
if(currenttime > 3600)
|
||||
remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.###} hours",
|
||||
currenttime/3600f), false);
|
||||
else if(currenttime > 60)
|
||||
remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.##} minutes",
|
||||
currenttime/60f), false);
|
||||
else
|
||||
remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.#} seconds",
|
||||
currenttime), false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LandAccessEntry entry = new LandAccessEntry();
|
||||
entry.AgentID = targetID;
|
||||
entry.Flags = AccessList.Access;
|
||||
entry.Expires = now + expires;
|
||||
if(currenttime > 0)
|
||||
entry.Expires += currenttime;
|
||||
IMoneyModule mm = m_scene.RequestModuleInterface<IMoneyModule>();
|
||||
if(cost != 0 && mm != null)
|
||||
{
|
||||
WorkManager.RunInThreadPool(
|
||||
delegate
|
||||
{
|
||||
string regionName = m_scene.RegionInfo.RegionName;
|
||||
|
||||
if (!mm.AmountCovered(remote_client.AgentId, cost))
|
||||
{
|
||||
remote_client.SendAgentAlertMessage(String.Format("Insufficient funds in region '{0}' money system", regionName), true);
|
||||
return;
|
||||
}
|
||||
|
||||
string payDescription = String.Format("Parcel '{0}' at region '{1} {2:0.###} hours access pass", ldata.Name, regionName, ldata.PassHours);
|
||||
|
||||
if(!mm.MoveMoney(remote_client.AgentId, ldata.OwnerID, cost,MoneyTransactionType.LandPassSale, payDescription))
|
||||
{
|
||||
remote_client.SendAgentAlertMessage("Sorry pass payment processing failed, please try again later", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx != -1)
|
||||
ldata.ParcelAccessList.RemoveAt(idx);
|
||||
ldata.ParcelAccessList.Add(entry);
|
||||
m_scene.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
|
||||
return;
|
||||
}, null, "ParcelBuyPass");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (idx != -1)
|
||||
ldata.ParcelAccessList.RemoveAt(idx);
|
||||
ldata.ParcelAccessList.Add(entry);
|
||||
m_scene.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientOnParcelAccessListRequest(UUID agentID, UUID sessionID, uint flags, int sequenceID,
|
||||
int landLocalID, IClientAPI remote_client)
|
||||
{
|
||||
|
@ -1292,7 +1406,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
{
|
||||
if (!temp.Contains(currentParcel))
|
||||
{
|
||||
if (!currentParcel.IsEitherBannedOrRestricted(remote_client.AgentId))
|
||||
if (!currentParcel.IsBannedFromLand(remote_client.AgentId))
|
||||
{
|
||||
currentParcel.ForceUpdateLandInfo();
|
||||
temp.Add(currentParcel);
|
||||
|
@ -1766,7 +1880,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
land_update.MusicURL = properties.MusicURL;
|
||||
land_update.Name = properties.Name;
|
||||
land_update.ParcelFlags = (uint) properties.ParcelFlags;
|
||||
land_update.PassHours = (int) properties.PassHours;
|
||||
land_update.PassHours = properties.PassHours;
|
||||
land_update.PassPrice = (int) properties.PassPrice;
|
||||
land_update.SalePrice = (int) properties.SalePrice;
|
||||
land_update.SnapshotID = properties.SnapshotID;
|
||||
|
|
|
@ -540,7 +540,8 @@ namespace OpenSim.Region.CoreModules.World.Land
|
|||
ParcelFlags.UseEstateVoiceChan);
|
||||
}
|
||||
|
||||
if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses, false))
|
||||
// don't allow passes on group owned until we can give money to groups
|
||||
if (!newData.IsGroupOwned && m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses, false))
|
||||
{
|
||||
newData.PassHours = args.PassHours;
|
||||
newData.PassPrice = args.PassPrice;
|
||||
|
|
|
@ -657,6 +657,9 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
|
||||
// if(!m_scene.IsRunning)
|
||||
// return sog;
|
||||
|
||||
if (root.KeyframeMotion != null)
|
||||
root.KeyframeMotion.StartCrossingCheck();
|
||||
|
||||
|
@ -3018,12 +3021,13 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
// If we somehow got here to updating the SOG and its root part is not scheduled for update,
|
||||
// check to see if the physical position or rotation warrant an update.
|
||||
/*
|
||||
if (m_rootPart.UpdateFlag == UpdateRequired.NONE)
|
||||
{
|
||||
// rootpart SendScheduledUpdates will check if a update is needed
|
||||
m_rootPart.UpdateFlag = UpdateRequired.TERSE;
|
||||
}
|
||||
|
||||
*/
|
||||
if (IsAttachment)
|
||||
{
|
||||
ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
|
||||
|
|
|
@ -238,12 +238,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// </remarks>
|
||||
public bool SoundQueueing { get; set; }
|
||||
|
||||
public uint TimeStampFull;
|
||||
|
||||
public uint TimeStampLastActivity; // Will be used for AutoReturn
|
||||
|
||||
public uint TimeStampTerse;
|
||||
|
||||
[XmlIgnore]
|
||||
public Quaternion AttachRotation = Quaternion.Identity;
|
||||
|
||||
|
@ -1219,6 +1213,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
|
||||
public UpdateRequired UpdateFlag { get; set; }
|
||||
private object UpdateFlagLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Used for media on a prim.
|
||||
|
@ -1641,8 +1636,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
PhysActor.SetMaterial((int)value);
|
||||
}
|
||||
if(ParentGroup != null)
|
||||
{
|
||||
ParentGroup.HasGroupChanged = true;
|
||||
ScheduleFullUpdateIfNone();
|
||||
ScheduleFullUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1675,7 +1672,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
get
|
||||
{
|
||||
byte pst = PhysicsShapeType;
|
||||
if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh())
|
||||
if(pst == (byte) PhysShapeType.none || HasMesh())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -1730,7 +1727,12 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
public byte PhysicsShapeType
|
||||
{
|
||||
get { return m_physicsShapeType; }
|
||||
get
|
||||
{
|
||||
// if (PhysActor != null)
|
||||
// m_physicsShapeType = PhysActor.PhysicsShapeType;
|
||||
return m_physicsShapeType;
|
||||
}
|
||||
set
|
||||
{
|
||||
byte oldv = m_physicsShapeType;
|
||||
|
@ -1781,10 +1783,12 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
m_density = value;
|
||||
|
||||
ScheduleFullUpdateIfNone();
|
||||
|
||||
if (ParentGroup != null)
|
||||
{
|
||||
ParentGroup.HasGroupChanged = true;
|
||||
ScheduleFullUpdate();
|
||||
}
|
||||
|
||||
PhysicsActor pa = PhysActor;
|
||||
if (pa != null)
|
||||
|
@ -1802,10 +1806,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
m_gravitymod = value;
|
||||
|
||||
ScheduleFullUpdateIfNone();
|
||||
|
||||
if (ParentGroup != null)
|
||||
{
|
||||
ParentGroup.HasGroupChanged = true;
|
||||
ScheduleFullUpdate();
|
||||
}
|
||||
|
||||
PhysicsActor pa = PhysActor;
|
||||
if (pa != null)
|
||||
|
@ -1823,10 +1828,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
m_friction = value;
|
||||
|
||||
ScheduleFullUpdateIfNone();
|
||||
|
||||
if (ParentGroup != null)
|
||||
{
|
||||
ParentGroup.HasGroupChanged = true;
|
||||
ScheduleFullUpdate();
|
||||
}
|
||||
|
||||
PhysicsActor pa = PhysActor;
|
||||
if (pa != null)
|
||||
|
@ -1844,10 +1850,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
m_bounce = value;
|
||||
|
||||
ScheduleFullUpdateIfNone();
|
||||
|
||||
if (ParentGroup != null)
|
||||
{
|
||||
ParentGroup.HasGroupChanged = true;
|
||||
ScheduleFullUpdate();
|
||||
}
|
||||
|
||||
PhysicsActor pa = PhysActor;
|
||||
if (pa != null)
|
||||
|
@ -1876,6 +1883,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// </summary>
|
||||
public void ClearUpdateSchedule()
|
||||
{
|
||||
lock(UpdateFlagLock)
|
||||
UpdateFlag = UpdateRequired.NONE;
|
||||
}
|
||||
|
||||
|
@ -3239,17 +3247,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
APIDActive = false;
|
||||
}
|
||||
|
||||
public void ScheduleFullUpdateIfNone()
|
||||
{
|
||||
if (ParentGroup == null)
|
||||
return;
|
||||
|
||||
// ??? ParentGroup.HasGroupChanged = true;
|
||||
|
||||
if (UpdateFlag != UpdateRequired.FULL)
|
||||
ScheduleFullUpdate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Schedules this prim for a full update
|
||||
/// </summary>
|
||||
|
@ -3260,22 +3257,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (ParentGroup == null)
|
||||
return;
|
||||
|
||||
ParentGroup.QueueForUpdateCheck();
|
||||
|
||||
int timeNow = Util.UnixTimeSinceEpoch();
|
||||
|
||||
// If multiple updates are scheduled on the same second, we still need to perform all of them
|
||||
// So we'll force the issue by bumping up the timestamp so that later processing sees these need
|
||||
// to be performed.
|
||||
if (timeNow <= TimeStampFull)
|
||||
lock(UpdateFlagLock)
|
||||
{
|
||||
TimeStampFull += 1;
|
||||
}
|
||||
else
|
||||
ParentGroup.QueueForUpdateCheck(); // just in case
|
||||
if(UpdateFlag != UpdateRequired.FULL)
|
||||
{
|
||||
TimeStampFull = (uint)timeNow;
|
||||
}
|
||||
|
||||
UpdateFlag = UpdateRequired.FULL;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
|
@ -3285,6 +3271,8 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (ParentGroup.Scene != null)
|
||||
ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Schedule a terse update for this prim. Terse updates only send position,
|
||||
|
@ -3304,12 +3292,13 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
return;
|
||||
}
|
||||
|
||||
lock(UpdateFlagLock)
|
||||
{
|
||||
if (UpdateFlag == UpdateRequired.NONE)
|
||||
{
|
||||
ParentGroup.HasGroupChanged = true;
|
||||
ParentGroup.QueueForUpdateCheck();
|
||||
|
||||
TimeStampTerse = (uint) Util.UnixTimeSinceEpoch();
|
||||
UpdateFlag = UpdateRequired.TERSE;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
|
@ -3320,6 +3309,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (ParentGroup.Scene != null)
|
||||
ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void ScriptSetPhysicsStatus(bool UsePhysics)
|
||||
{
|
||||
|
@ -3362,12 +3352,15 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
return;
|
||||
|
||||
// Update the "last" values
|
||||
lock(UpdateFlagLock)
|
||||
{
|
||||
m_lastPosition = AbsolutePosition;
|
||||
m_lastRotation = RotationOffset;
|
||||
m_lastVelocity = Velocity;
|
||||
m_lastAcceleration = Acceleration;
|
||||
m_lastAngularVelocity = AngularVelocity;
|
||||
m_lastUpdateSentTime = Util.GetTimeStampMS();
|
||||
}
|
||||
|
||||
ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
|
||||
{
|
||||
|
@ -3381,12 +3374,15 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
return;
|
||||
|
||||
// Update the "last" values
|
||||
lock(UpdateFlagLock)
|
||||
{
|
||||
m_lastPosition = AbsolutePosition;
|
||||
m_lastRotation = RotationOffset;
|
||||
m_lastVelocity = Velocity;
|
||||
m_lastAcceleration = Acceleration;
|
||||
m_lastAngularVelocity = AngularVelocity;
|
||||
m_lastUpdateSentTime = Util.GetTimeStampMS();
|
||||
}
|
||||
|
||||
if (ParentGroup.IsAttachment)
|
||||
{
|
||||
|
@ -3443,16 +3439,22 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// </summary>
|
||||
public void SendScheduledUpdates()
|
||||
{
|
||||
switch (UpdateFlag)
|
||||
UpdateRequired currentUpdate;
|
||||
lock(UpdateFlagLock)
|
||||
{
|
||||
currentUpdate = UpdateFlag;
|
||||
ClearUpdateSchedule();
|
||||
}
|
||||
|
||||
switch (currentUpdate)
|
||||
{
|
||||
case UpdateRequired.NONE:
|
||||
ClearUpdateSchedule();
|
||||
break;
|
||||
|
||||
case UpdateRequired.TERSE:
|
||||
|
||||
ClearUpdateSchedule();
|
||||
bool needupdate = true;
|
||||
lock(UpdateFlagLock)
|
||||
{
|
||||
double now = Util.GetTimeStampMS();
|
||||
Vector3 curvel = Velocity;
|
||||
Vector3 curacc = Acceleration;
|
||||
|
@ -3543,7 +3545,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_lastAcceleration = curacc;
|
||||
m_lastAngularVelocity = angvel;
|
||||
m_lastUpdateSentTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
if(needupdate)
|
||||
{
|
||||
ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
|
||||
{
|
||||
SendTerseUpdateToClient(client);
|
||||
|
@ -3552,7 +3558,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
break;
|
||||
|
||||
case UpdateRequired.FULL:
|
||||
ClearUpdateSchedule();
|
||||
SendFullUpdateToAllClientsInternal();
|
||||
break;
|
||||
}
|
||||
|
@ -3567,7 +3572,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (ParentGroup == null || ParentGroup.Scene == null)
|
||||
return;
|
||||
|
||||
ClearUpdateSchedule();
|
||||
lock(UpdateFlagLock)
|
||||
{
|
||||
if(UpdateFlag != UpdateRequired.NONE)
|
||||
return;
|
||||
|
||||
// Update the "last" values
|
||||
m_lastPosition = AbsolutePosition;
|
||||
|
@ -3576,6 +3584,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_lastAcceleration = Acceleration;
|
||||
m_lastAngularVelocity = AngularVelocity;
|
||||
m_lastUpdateSentTime = Util.GetTimeStampMS();
|
||||
}
|
||||
|
||||
ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
|
||||
{
|
||||
|
@ -3588,7 +3597,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (ParentGroup == null || ParentGroup.Scene == null)
|
||||
return;
|
||||
|
||||
ClearUpdateSchedule();
|
||||
lock(UpdateFlagLock)
|
||||
{
|
||||
if(UpdateFlag != UpdateRequired.NONE)
|
||||
return;
|
||||
|
||||
// Update the "last" values
|
||||
m_lastPosition = AbsolutePosition;
|
||||
|
@ -3597,6 +3609,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_lastAcceleration = Acceleration;
|
||||
m_lastAngularVelocity = AngularVelocity;
|
||||
m_lastUpdateSentTime = Util.GetTimeStampMS();
|
||||
}
|
||||
|
||||
if (ParentGroup.IsAttachment)
|
||||
{
|
||||
|
|
|
@ -844,9 +844,14 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
|
|||
module.BuyObject(remoteClient, categoryID, localID, saleType, salePrice);
|
||||
}
|
||||
|
||||
public void MoveMoney(UUID fromAgentID, UUID toAgentID, int amount, string text)
|
||||
public void MoveMoney(UUID fromUser, UUID toUser, int amount, string text)
|
||||
{
|
||||
}
|
||||
|
||||
public bool MoveMoney(UUID fromUser, UUID toUser, int amount, MoneyTransactionType type, string text)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public enum TransactionType : int
|
||||
|
|
|
@ -141,14 +141,30 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
|
|||
}
|
||||
|
||||
// The passed position is relative to the base of the region.
|
||||
// There are many assumptions herein that the heightmap increment is 1.
|
||||
public override float GetTerrainHeightAtXYZ(Vector3 pos)
|
||||
{
|
||||
float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
|
||||
|
||||
int mapIndex = (int)pos.Y * (int)m_mapInfo.sizeY + (int)pos.X;
|
||||
try
|
||||
{
|
||||
ret = m_mapInfo.heightMap[mapIndex];
|
||||
try {
|
||||
int baseX = (int)pos.X;
|
||||
int baseY = (int)pos.Y;
|
||||
int maxX = (int)m_mapInfo.sizeX;
|
||||
int maxY = (int)m_mapInfo.sizeY;
|
||||
float diffX = pos.X - (float)baseX;
|
||||
float diffY = pos.Y - (float)baseY;
|
||||
|
||||
float mapHeight1 = m_mapInfo.heightMap[baseY * maxY + baseX];
|
||||
float mapHeight2 = m_mapInfo.heightMap[Math.Min(baseY + 1, maxY - 1) * maxY + baseX];
|
||||
float mapHeight3 = m_mapInfo.heightMap[baseY * maxY + Math.Min(baseX + 1, maxX - 1)];
|
||||
float mapHeight4 = m_mapInfo.heightMap[Math.Min(baseY + 1, maxY - 1) * maxY + Math.Min(baseX + 1, maxX - 1)];
|
||||
|
||||
float Xrise = (mapHeight4 - mapHeight3) * diffX;
|
||||
float Yrise = (mapHeight2 - mapHeight1) * diffY;
|
||||
|
||||
ret = mapHeight1 + ((Xrise + Yrise) / 2f);
|
||||
// m_physicsScene.DetailLog("{0},BSTerrainHeightMap,GetTerrainHeightAtXYZ,pos={1},{2}/{3}/{4}/{5},ret={6}",
|
||||
// BSScene.DetailLogZero, pos, mapHeight1, mapHeight2, mapHeight3, mapHeight4, ret);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace OpenSim.Region.PhysicsModule.Meshing
|
|||
|
||||
private bool cacheSculptMaps = true;
|
||||
private string decodedSculptMapPath = null;
|
||||
private bool useMeshiesPhysicsMesh = false;
|
||||
private bool useMeshiesPhysicsMesh = true;
|
||||
|
||||
private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
|
|||
public byte shapetype;
|
||||
public bool hasOBB;
|
||||
public bool hasMeshVolume;
|
||||
public bool isTooSmall;
|
||||
public MeshState meshState;
|
||||
public UUID? assetID;
|
||||
public meshWorkerCmnds comand;
|
||||
|
@ -69,16 +70,14 @@ namespace OpenSim.Region.PhysicsModule.ubOde
|
|||
|
||||
public class ODEMeshWorker
|
||||
{
|
||||
|
||||
private ILog m_log;
|
||||
private ODEScene m_scene;
|
||||
private IMesher m_mesher;
|
||||
|
||||
public bool meshSculptedPrim = true;
|
||||
public bool forceSimplePrimMeshing = false;
|
||||
public float meshSculptLOD = 32;
|
||||
public float MeshSculptphysicalLOD = 32;
|
||||
|
||||
public float MinSizeToMeshmerize = 0.1f;
|
||||
|
||||
private OpenSim.Framework.BlockingQueue<ODEPhysRepData> workQueue = new OpenSim.Framework.BlockingQueue<ODEPhysRepData>();
|
||||
private bool m_running;
|
||||
|
@ -93,9 +92,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde
|
|||
|
||||
if (pConfig != null)
|
||||
{
|
||||
forceSimplePrimMeshing = pConfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
|
||||
meshSculptedPrim = pConfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
|
||||
meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD);
|
||||
MinSizeToMeshmerize = pConfig.GetFloat("mesh_min_size", MinSizeToMeshmerize);
|
||||
MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
|
||||
}
|
||||
m_running = true;
|
||||
|
@ -288,6 +287,16 @@ namespace OpenSim.Region.PhysicsModule.ubOde
|
|||
{
|
||||
PrimitiveBaseShape pbs = repData.pbs;
|
||||
// check sculpts or meshs
|
||||
|
||||
Vector3 scale = pbs.Scale;
|
||||
if(scale.X <= MinSizeToMeshmerize &&
|
||||
scale.Y <= MinSizeToMeshmerize &&
|
||||
scale.Z <= MinSizeToMeshmerize)
|
||||
{
|
||||
repData.isTooSmall = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pbs.SculptEntry)
|
||||
{
|
||||
if (meshSculptedPrim)
|
||||
|
@ -299,9 +308,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde
|
|||
return false;
|
||||
}
|
||||
|
||||
if (forceSimplePrimMeshing)
|
||||
return true;
|
||||
|
||||
// convex shapes have no holes
|
||||
ushort profilehollow = pbs.ProfileHollow;
|
||||
if(repData.shapetype == 2)
|
||||
|
@ -425,17 +431,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde
|
|||
Vector3 size = repData.size;
|
||||
|
||||
int clod = (int)LevelOfDetail.High;
|
||||
bool convex;
|
||||
byte shapetype = repData.shapetype;
|
||||
if (shapetype == 0)
|
||||
convex = false;
|
||||
else
|
||||
{
|
||||
convex = true;
|
||||
// sculpts pseudo convex
|
||||
if (pbs.SculptEntry && pbs.SculptType != (byte)SculptType.Mesh)
|
||||
clod = (int)LevelOfDetail.Low;
|
||||
}
|
||||
bool convex = shapetype == 2;
|
||||
|
||||
mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
|
||||
|
||||
|
@ -563,10 +560,16 @@ namespace OpenSim.Region.PhysicsModule.ubOde
|
|||
|
||||
private void CalculateBasicPrimVolume(ODEPhysRepData repData)
|
||||
{
|
||||
PrimitiveBaseShape _pbs = repData.pbs;
|
||||
Vector3 _size = repData.size;
|
||||
|
||||
float volume = _size.X * _size.Y * _size.Z; // default
|
||||
if(repData.isTooSmall)
|
||||
{
|
||||
repData.volume = volume;
|
||||
return;
|
||||
}
|
||||
|
||||
PrimitiveBaseShape _pbs = repData.pbs;
|
||||
float tmp;
|
||||
|
||||
float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
|
||||
|
|
|
@ -1733,7 +1733,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
|
|||
return true;
|
||||
}
|
||||
|
||||
private void CreateGeom()
|
||||
private void CreateGeom(bool OverrideToBox)
|
||||
{
|
||||
bool hasMesh = false;
|
||||
|
||||
|
@ -1742,7 +1742,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
|
|||
if ((m_meshState & MeshState.MeshNoColide) != 0)
|
||||
m_NoColide = true;
|
||||
|
||||
else if(m_mesh != null)
|
||||
else if(!OverrideToBox && m_mesh != null)
|
||||
{
|
||||
if (GetMeshGeom())
|
||||
hasMesh = true;
|
||||
|
@ -3180,7 +3180,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
|
|||
|
||||
primVolume = repData.volume;
|
||||
|
||||
CreateGeom();
|
||||
CreateGeom(repData.isTooSmall);
|
||||
|
||||
if (prim_geom != IntPtr.Zero)
|
||||
{
|
||||
|
@ -3256,7 +3256,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
|
|||
|
||||
primVolume = repData.volume;
|
||||
|
||||
CreateGeom();
|
||||
CreateGeom(repData.isTooSmall);
|
||||
|
||||
if (prim_geom != IntPtr.Zero)
|
||||
{
|
||||
|
|
|
@ -36,15 +36,13 @@ using OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet;
|
|||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Threading;
|
||||
using System.IO.Compression;
|
||||
using PrimMesher;
|
||||
using log4net;
|
||||
using Nini.Config;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
using Mono.Addins;
|
||||
|
||||
|
@ -58,22 +56,22 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
|
|||
// Setting baseDir to a path will enable the dumping of raw files
|
||||
// raw files can be imported by blender so a visual inspection of the results can be done
|
||||
|
||||
private static string cacheControlFilename = "cntr";
|
||||
private bool m_Enabled = false;
|
||||
|
||||
public static object diskLock = new object();
|
||||
|
||||
public bool doMeshFileCache = true;
|
||||
|
||||
public bool doCacheExpire = true;
|
||||
public string cachePath = "MeshCache";
|
||||
public TimeSpan CacheExpire;
|
||||
public bool doCacheExpire = true;
|
||||
|
||||
// const string baseDir = "rawFiles";
|
||||
private const string baseDir = null; //"rawFiles";
|
||||
|
||||
private bool useMeshiesPhysicsMesh = false;
|
||||
|
||||
private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
|
||||
private bool useMeshiesPhysicsMesh = true;
|
||||
private bool doConvexPrims = true;
|
||||
private bool doConvexSculpts = true;
|
||||
|
||||
private Dictionary<AMeshKey, Mesh> m_uniqueMeshes = new Dictionary<AMeshKey, Mesh>();
|
||||
private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = new Dictionary<AMeshKey, Mesh>();
|
||||
|
@ -103,40 +101,31 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
|
|||
if (mesh_config != null)
|
||||
{
|
||||
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
|
||||
if (useMeshiesPhysicsMesh)
|
||||
{
|
||||
doConvexPrims = mesh_config.GetBoolean("ConvexPrims",doConvexPrims);
|
||||
doConvexSculpts = mesh_config.GetBoolean("ConvexSculpts",doConvexPrims);
|
||||
doMeshFileCache = mesh_config.GetBoolean("MeshFileCache", doMeshFileCache);
|
||||
cachePath = mesh_config.GetString("MeshFileCachePath", cachePath);
|
||||
fcache = mesh_config.GetFloat("MeshFileCacheExpireHours", fcache);
|
||||
doCacheExpire = mesh_config.GetBoolean("MeshFileCacheDoExpire", doCacheExpire);
|
||||
}
|
||||
else
|
||||
{
|
||||
doMeshFileCache = false;
|
||||
doCacheExpire = false;
|
||||
}
|
||||
|
||||
m_Enabled = true;
|
||||
}
|
||||
|
||||
CacheExpire = TimeSpan.FromHours(fcache);
|
||||
|
||||
lock (diskLock)
|
||||
if(String.IsNullOrEmpty(cachePath))
|
||||
doMeshFileCache = false;
|
||||
|
||||
if(doMeshFileCache)
|
||||
{
|
||||
if(doMeshFileCache && cachePath != "")
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(cachePath))
|
||||
Directory.CreateDirectory(cachePath);
|
||||
}
|
||||
catch
|
||||
if(!checkCache())
|
||||
{
|
||||
doMeshFileCache = false;
|
||||
doCacheExpire = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
doCacheExpire = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,87 +157,6 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
|
|||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// creates a simple box mesh of the specified size. This mesh is of very low vertex count and may
|
||||
/// be useful as a backup proxy when level of detail is not needed or when more complex meshes fail
|
||||
/// for some reason
|
||||
/// </summary>
|
||||
/// <param name="minX"></param>
|
||||
/// <param name="maxX"></param>
|
||||
/// <param name="minY"></param>
|
||||
/// <param name="maxY"></param>
|
||||
/// <param name="minZ"></param>
|
||||
/// <param name="maxZ"></param>
|
||||
/// <returns></returns>
|
||||
private static Mesh CreateSimpleBoxMesh(float minX, float maxX, float minY, float maxY, float minZ, float maxZ)
|
||||
{
|
||||
Mesh box = new Mesh(true);
|
||||
List<Vertex> vertices = new List<Vertex>();
|
||||
// bottom
|
||||
|
||||
vertices.Add(new Vertex(minX, maxY, minZ));
|
||||
vertices.Add(new Vertex(maxX, maxY, minZ));
|
||||
vertices.Add(new Vertex(maxX, minY, minZ));
|
||||
vertices.Add(new Vertex(minX, minY, minZ));
|
||||
|
||||
box.Add(new Triangle(vertices[0], vertices[1], vertices[2]));
|
||||
box.Add(new Triangle(vertices[0], vertices[2], vertices[3]));
|
||||
|
||||
// top
|
||||
|
||||
vertices.Add(new Vertex(maxX, maxY, maxZ));
|
||||
vertices.Add(new Vertex(minX, maxY, maxZ));
|
||||
vertices.Add(new Vertex(minX, minY, maxZ));
|
||||
vertices.Add(new Vertex(maxX, minY, maxZ));
|
||||
|
||||
box.Add(new Triangle(vertices[4], vertices[5], vertices[6]));
|
||||
box.Add(new Triangle(vertices[4], vertices[6], vertices[7]));
|
||||
|
||||
// sides
|
||||
|
||||
box.Add(new Triangle(vertices[5], vertices[0], vertices[3]));
|
||||
box.Add(new Triangle(vertices[5], vertices[3], vertices[6]));
|
||||
|
||||
box.Add(new Triangle(vertices[1], vertices[0], vertices[5]));
|
||||
box.Add(new Triangle(vertices[1], vertices[5], vertices[4]));
|
||||
|
||||
box.Add(new Triangle(vertices[7], vertices[1], vertices[4]));
|
||||
box.Add(new Triangle(vertices[7], vertices[2], vertices[1]));
|
||||
|
||||
box.Add(new Triangle(vertices[3], vertices[2], vertices[7]));
|
||||
box.Add(new Triangle(vertices[3], vertices[7], vertices[6]));
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a simple bounding box mesh for a complex input mesh
|
||||
/// </summary>
|
||||
/// <param name="meshIn"></param>
|
||||
/// <returns></returns>
|
||||
private static Mesh CreateBoundingBoxMesh(Mesh meshIn)
|
||||
{
|
||||
float minX = float.MaxValue;
|
||||
float maxX = float.MinValue;
|
||||
float minY = float.MaxValue;
|
||||
float maxY = float.MinValue;
|
||||
float minZ = float.MaxValue;
|
||||
float maxZ = float.MinValue;
|
||||
|
||||
foreach (Vector3 v in meshIn.getVertexList())
|
||||
{
|
||||
if (v.X < minX) minX = v.X;
|
||||
if (v.Y < minY) minY = v.Y;
|
||||
if (v.Z < minZ) minZ = v.Z;
|
||||
|
||||
if (v.X > maxX) maxX = v.X;
|
||||
if (v.Y > maxY) maxY = v.Y;
|
||||
if (v.Z > maxZ) maxZ = v.Z;
|
||||
}
|
||||
|
||||
return CreateSimpleBoxMesh(minX, maxX, minY, maxY, minZ, maxZ);
|
||||
}
|
||||
|
||||
private void ReportPrimError(string message, string primName, PrimMesh primMesh)
|
||||
{
|
||||
m_log.Error(message);
|
||||
|
@ -330,6 +238,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
|
|||
|
||||
List<Coord> coords;
|
||||
List<Face> faces;
|
||||
bool needsConvexProcessing = convex;
|
||||
|
||||
if (primShape.SculptEntry)
|
||||
{
|
||||
|
@ -340,23 +249,49 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
|
|||
|
||||
if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, out coords, out faces, convex))
|
||||
return null;
|
||||
needsConvexProcessing = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, lod, out coords, out faces))
|
||||
return null;
|
||||
needsConvexProcessing &= doConvexSculpts;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, lod, convex, out coords, out faces))
|
||||
return null;
|
||||
needsConvexProcessing &= doConvexPrims;
|
||||
}
|
||||
|
||||
|
||||
int numCoords = coords.Count;
|
||||
int numFaces = faces.Count;
|
||||
|
||||
if(numCoords < 3 || (!needsConvexProcessing && numFaces < 1))
|
||||
{
|
||||
m_log.ErrorFormat("[MESH]: invalid degenerated mesh for prim {0} ignored", primName);
|
||||
return null;
|
||||
}
|
||||
|
||||
if(needsConvexProcessing)
|
||||
{
|
||||
List<Coord> convexcoords;
|
||||
List<Face> convexfaces;
|
||||
if(CreateBoundingHull(coords, out convexcoords, out convexfaces) && convexcoords != null && convexfaces != null)
|
||||
{
|
||||
coords.Clear();
|
||||
coords = convexcoords;
|
||||
numCoords = coords.Count;
|
||||
|
||||
faces.Clear();
|
||||
faces = convexfaces;
|
||||
numFaces = faces.Count;
|
||||
}
|
||||
else
|
||||
m_log.ErrorFormat("[ubMESH]: failed to create convex for {0} using normal mesh", primName);
|
||||
}
|
||||
|
||||
Mesh mesh = new Mesh(true);
|
||||
// Add the corresponding triangles to the mesh
|
||||
for (int i = 0; i < numFaces; i++)
|
||||
|
@ -372,7 +307,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
|
|||
|
||||
if(mesh.numberVertices() < 3 || mesh.numberTriangles() < 1)
|
||||
{
|
||||
m_log.ErrorFormat("[MESH]: invalid degenerated mesh for prim " + primName + " ignored");
|
||||
m_log.ErrorFormat("[MESH]: invalid degenerated mesh for prim {0} ignored", primName);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -625,45 +560,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
|
|||
vs.Clear();
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
if (!HullUtils.ComputeHull(vs, ref hullr, 0, 0.0f))
|
||||
{
|
||||
vs.Clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
nverts = hullr.Vertices.Count;
|
||||
nindexs = hullr.Indices.Count;
|
||||
|
||||
if (nindexs % 3 != 0)
|
||||
{
|
||||
vs.Clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < nverts; i++)
|
||||
{
|
||||
c.X = hullr.Vertices[i].x;
|
||||
c.Y = hullr.Vertices[i].y;
|
||||
c.Z = hullr.Vertices[i].z;
|
||||
coords.Add(c);
|
||||
}
|
||||
|
||||
for (i = 0; i < nindexs; i += 3)
|
||||
{
|
||||
t1 = hullr.Indices[i];
|
||||
if (t1 > nverts)
|
||||
break;
|
||||
t2 = hullr.Indices[i + 1];
|
||||
if (t2 > nverts)
|
||||
break;
|
||||
t3 = hullr.Indices[i + 2];
|
||||
if (t3 > nverts)
|
||||
break;
|
||||
f = new Face(vertsoffset + t1, vertsoffset + t2, vertsoffset + t3);
|
||||
faces.Add(f);
|
||||
}
|
||||
*/
|
||||
List<int> indices;
|
||||
if (!HullUtils.ComputeHull(vs, out indices))
|
||||
{
|
||||
|
@ -769,38 +666,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
|
|||
vs.Clear();
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
if (!HullUtils.ComputeHull(vs, ref hullr, 0, 0.0f))
|
||||
return false;
|
||||
|
||||
nverts = hullr.Vertices.Count;
|
||||
nindexs = hullr.Indices.Count;
|
||||
|
||||
if (nindexs % 3 != 0)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < nverts; i++)
|
||||
{
|
||||
c.X = hullr.Vertices[i].x;
|
||||
c.Y = hullr.Vertices[i].y;
|
||||
c.Z = hullr.Vertices[i].z;
|
||||
coords.Add(c);
|
||||
}
|
||||
for (i = 0; i < nindexs; i += 3)
|
||||
{
|
||||
t1 = hullr.Indices[i];
|
||||
if (t1 > nverts)
|
||||
break;
|
||||
t2 = hullr.Indices[i + 1];
|
||||
if (t2 > nverts)
|
||||
break;
|
||||
t3 = hullr.Indices[i + 2];
|
||||
if (t3 > nverts)
|
||||
break;
|
||||
f = new Face(t1, t2, t3);
|
||||
faces.Add(f);
|
||||
}
|
||||
*/
|
||||
List<int> indices;
|
||||
if (!HullUtils.ComputeHull(vs, out indices))
|
||||
return false;
|
||||
|
@ -1413,7 +1279,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
|
|||
}
|
||||
}
|
||||
|
||||
public void FileNames(AMeshKey key, out string dir,out string fullFileName)
|
||||
public void FileNames(AMeshKey key, out string dir, out string fullFileName)
|
||||
{
|
||||
string id = key.ToString();
|
||||
string init = id.Substring(0, 1);
|
||||
|
@ -1530,7 +1396,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
|
|||
if (!doCacheExpire)
|
||||
return;
|
||||
|
||||
string controlfile = System.IO.Path.Combine(cachePath, "cntr");
|
||||
string controlfile = System.IO.Path.Combine(cachePath, cacheControlFilename);
|
||||
|
||||
lock (diskLock)
|
||||
{
|
||||
|
@ -1583,5 +1449,153 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
|
|||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
public bool checkCache()
|
||||
{
|
||||
string controlfile = System.IO.Path.Combine(cachePath, cacheControlFilename);
|
||||
lock (diskLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(cachePath))
|
||||
{
|
||||
Directory.CreateDirectory(cachePath);
|
||||
Thread.Sleep(100);
|
||||
FileStream fs = File.Create(controlfile, 4096, FileOptions.WriteThrough);
|
||||
fs.Close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
doMeshFileCache = false;
|
||||
doCacheExpire = false;
|
||||
return false;
|
||||
}
|
||||
finally {}
|
||||
|
||||
if (File.Exists(controlfile))
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
Directory.Delete(cachePath, true);
|
||||
while(Directory.Exists(cachePath))
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
m_log.Error("[MESH CACHE]: failed to delete old version of the cache: " + e.Message);
|
||||
doMeshFileCache = false;
|
||||
doCacheExpire = false;
|
||||
return false;
|
||||
}
|
||||
finally {}
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(cachePath);
|
||||
while(!Directory.Exists(cachePath))
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
m_log.Error("[MESH CACHE]: failed to create new cache folder: " + e.Message);
|
||||
doMeshFileCache = false;
|
||||
doCacheExpire = false;
|
||||
return false;
|
||||
}
|
||||
finally {}
|
||||
|
||||
try
|
||||
{
|
||||
FileStream fs = File.Create(controlfile, 4096, FileOptions.WriteThrough);
|
||||
fs.Close();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
m_log.Error("[MESH CACHE]: failed to create new control file: " + e.Message);
|
||||
doMeshFileCache = false;
|
||||
doCacheExpire = false;
|
||||
return false;
|
||||
}
|
||||
finally {}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CreateBoundingHull(List<Coord> inputVertices, out List<Coord> convexcoords, out List<Face> newfaces)
|
||||
{
|
||||
convexcoords = null;
|
||||
newfaces = null;
|
||||
HullDesc desc = new HullDesc();
|
||||
HullResult result = new HullResult();
|
||||
|
||||
int nInputVerts = inputVertices.Count;
|
||||
int i;
|
||||
|
||||
List<float3> vs = new List<float3>(nInputVerts);
|
||||
float3 f3;
|
||||
|
||||
//useless copy
|
||||
for(i = 0 ; i < nInputVerts; i++)
|
||||
{
|
||||
f3 = new float3(inputVertices[i].X, inputVertices[i].Y, inputVertices[i].Z);
|
||||
vs.Add(f3);
|
||||
}
|
||||
|
||||
desc.Vertices = vs;
|
||||
desc.Flags = HullFlag.QF_TRIANGLES;
|
||||
desc.MaxVertices = 256;
|
||||
|
||||
try
|
||||
{
|
||||
HullError ret = HullUtils.CreateConvexHull(desc, ref result);
|
||||
if (ret != HullError.QE_OK)
|
||||
return false;
|
||||
int nverts = result.OutputVertices.Count;
|
||||
int nindx = result.Indices.Count;
|
||||
if(nverts < 3 || nindx< 3)
|
||||
return false;
|
||||
if(nindx % 3 != 0)
|
||||
return false;
|
||||
|
||||
convexcoords = new List<Coord>(nverts);
|
||||
Coord c;
|
||||
vs = result.OutputVertices;
|
||||
|
||||
for(i = 0 ; i < nverts; i++)
|
||||
{
|
||||
c = new Coord(vs[i].x, vs[i].y, vs[i].z);
|
||||
convexcoords.Add(c);
|
||||
}
|
||||
|
||||
newfaces = new List<Face>(nindx / 3);
|
||||
List<int> indxs = result.Indices;
|
||||
int k, l, m;
|
||||
Face f;
|
||||
for(i = 0 ; i < nindx;)
|
||||
{
|
||||
k = indxs[i++];
|
||||
l = indxs[i++];
|
||||
m = indxs[i++];
|
||||
if(k > nInputVerts)
|
||||
continue;
|
||||
if(l > nInputVerts)
|
||||
continue;
|
||||
if(m > nInputVerts)
|
||||
continue;
|
||||
f = new Face(k,l,m);
|
||||
newfaces.Add(f);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7851,7 +7851,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
UUID key;
|
||||
ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
|
||||
|
||||
if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned, false))
|
||||
if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManagePasses, false))
|
||||
{
|
||||
int expires = 0;
|
||||
if (hours != 0)
|
||||
|
@ -13073,7 +13073,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
m_host.AddScriptLPS(1);
|
||||
UUID key;
|
||||
ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
|
||||
if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed, false))
|
||||
if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManagePasses, false))
|
||||
{
|
||||
if (UUID.TryParse(avatar, out key))
|
||||
{
|
||||
|
|
|
@ -525,7 +525,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
|||
}
|
||||
|
||||
[Serializable]
|
||||
public class list: MarshalByRefObject
|
||||
public class list
|
||||
{
|
||||
private object[] m_data;
|
||||
|
||||
|
|
|
@ -395,6 +395,7 @@ namespace OpenSim.Services.HypergridService
|
|||
{
|
||||
if(SendAgentGodKillToRegion(UUID.Zero, agentID, guinfo))
|
||||
{
|
||||
if(account != null)
|
||||
m_log.InfoFormat(
|
||||
"[GATEKEEPER SERVICE]: Login failed for {0} {1}, reason: already logged in",
|
||||
account.FirstName, account.LastName);
|
||||
|
|
|
@ -44,6 +44,13 @@ namespace OpenSim.Tests.Permissions
|
|||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
// In case we're dealing with some older version of nunit
|
||||
if (Common.TheInstance == null)
|
||||
{
|
||||
Common.TheInstance = new Common();
|
||||
Common.TheInstance.SetUp();
|
||||
}
|
||||
|
||||
Common.TheInstance.DeleteObjectsFolders();
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,12 @@ namespace OpenSim.Tests.Permissions
|
|||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
// In case we're dealing with some older version of nunit
|
||||
if (Common.TheInstance == null)
|
||||
{
|
||||
Common.TheInstance = new Common();
|
||||
Common.TheInstance.SetUp();
|
||||
}
|
||||
Common.TheInstance.DeleteObjectsFolders();
|
||||
}
|
||||
|
||||
|
@ -74,6 +80,7 @@ namespace OpenSim.Tests.Permissions
|
|||
// Try A2 takes copies of objects that cannot be copied.
|
||||
for (int i = 0; i < 6; i++)
|
||||
TakeOneBox(Common.TheScene.GetSceneObjectGroups(), names[i], perms[i]);
|
||||
// Ad-hoc. Enough time to let the take work.
|
||||
Thread.Sleep(5000);
|
||||
|
||||
List<InventoryItemBase> items = Common.TheScene.InventoryService.GetFolderItems(Common.TheAvatars[1].UUID, objsFolder.ID);
|
||||
|
@ -86,6 +93,7 @@ namespace OpenSim.Tests.Permissions
|
|||
// Try A2 takes copies of objects that can be copied.
|
||||
for (int i = 0; i < 6; i++)
|
||||
TakeOneBox(Common.TheScene.GetSceneObjectGroups(), names[i], perms[i]);
|
||||
// Ad-hoc. Enough time to let the take work.
|
||||
Thread.Sleep(5000);
|
||||
|
||||
items = Common.TheScene.InventoryService.GetFolderItems(Common.TheAvatars[1].UUID, objsFolder.ID);
|
||||
|
@ -101,6 +109,7 @@ namespace OpenSim.Tests.Permissions
|
|||
|
||||
private void TakeOneBox(List<SceneObjectGroup> objs, string name, PermissionMask mask)
|
||||
{
|
||||
// Find the object inworld
|
||||
SceneObjectGroup box = objs.Find(sog => sog.Name == name && sog.OwnerID == Common.TheAvatars[0].UUID);
|
||||
Assert.That(box, Is.Not.Null, name);
|
||||
|
||||
|
|
|
@ -949,18 +949,35 @@
|
|||
|
||||
|
||||
[Mesh]
|
||||
; enable / disable Collada mesh support
|
||||
; enable / disable mesh asset uploads
|
||||
; mesh asset must conform to standard mesh format, with OpenSim extensions
|
||||
; default is true
|
||||
AllowMeshUpload = true
|
||||
|
||||
; if you use Meshmerizer and want collisions for meshies, setting this to true
|
||||
; will cause OpenSim to attempt to decode meshies assets, extract the physics
|
||||
; mesh, and use it for collisions.
|
||||
UseMeshiesPhysicsMesh = true
|
||||
|
||||
; Minimum user level required to upload meshes
|
||||
;LevelUpload = 0
|
||||
|
||||
; support meshes on physics
|
||||
;UseMeshiesPhysicsMesh = true
|
||||
|
||||
;support convex shape type on normal prims
|
||||
; (ubOde only)
|
||||
;ConvexPrims = true
|
||||
|
||||
;support convex shape type on sculpts
|
||||
; (ubOde only)
|
||||
;ConvexSculpts = true
|
||||
|
||||
; mesh cache settings:
|
||||
; (ubOde only)
|
||||
; do cache (keep true)
|
||||
;MeshFileCache = true
|
||||
; cache folder name relative to bin/ or absolute path
|
||||
;MeshFileCachePath = MeshCache
|
||||
;MeshFileCacheDoExpire = true;
|
||||
;MeshFileCacheExpireHours = 48
|
||||
|
||||
|
||||
|
||||
[Textures]
|
||||
; If true, textures generated dynamically (i.e. through osSetDynamicTextureData() and similar OSSL functions) are reused where possible
|
||||
|
@ -982,7 +999,7 @@
|
|||
|
||||
[ODEPhysicsSettings]
|
||||
; ##
|
||||
; ## Physics stats settings
|
||||
; ## Physics stats settings ( most ignored by ubOde )
|
||||
;
|
||||
|
||||
; If collect_stats is enabled, then extra stat information is collected which is accessible via the MonitorModule
|
||||
|
@ -1155,12 +1172,14 @@
|
|||
; ## additional meshing options
|
||||
; ##
|
||||
|
||||
; Physical collision mesh proxies are normally created for complex prim shapes,
|
||||
; and collisions for simple boxes and spheres are computed algorithmically.
|
||||
; If you would rather have mesh proxies for simple prims, you can set this to
|
||||
; true. Note that this will increase memory usage and region startup time.
|
||||
; Default is false.
|
||||
;force_simple_prim_meshing = false
|
||||
; Physics needs to create internal meshs (or convert the object meshs or scultps)
|
||||
; for all prims except simple boxes and spheres.
|
||||
|
||||
; collisions of small objects againts larger ones can have a increased CPU load cost
|
||||
; so this are represented by a simple BOX
|
||||
; if all their scale dimensions are lower or equal to this option. Default is 0.1m
|
||||
; (ubOde only)
|
||||
; MinSizeToMeshmerize = 0.1
|
||||
|
||||
|
||||
[BulletSim]
|
||||
|
@ -1469,7 +1488,7 @@
|
|||
|
||||
; active_trees allows module to change its trees in time.
|
||||
; some will be deleted, others created and rest may grow
|
||||
; default is false. You can change it with console comand tree active true | false later
|
||||
; default is false. You can change it with console command tree active true | false later
|
||||
active_trees = false
|
||||
; the trees change execution time rate (in ms)
|
||||
update_rate = 1000
|
||||
|
@ -2061,7 +2080,7 @@
|
|||
;XmlRpcServiceWriteKey = 1234
|
||||
|
||||
; Disables HTTP Keep-Alive for XmlRpcGroupsServicesConnector HTTP Requests,
|
||||
; only set to false it if you absolute sure regions and groups server suport it.
|
||||
; only set to false it if you absolute sure regions and groups server support it.
|
||||
; XmlRpcDisableKeepAlive = true
|
||||
|
||||
; Minimum user level required to create groups
|
||||
|
|
|
@ -36,9 +36,6 @@
|
|||
SimulationServiceInConnector = true
|
||||
LibraryModule = true
|
||||
|
||||
[Profile]
|
||||
Module = "BasicProfileModule"
|
||||
|
||||
[SimulationDataStore]
|
||||
LocalServiceModule = "OpenSim.Services.SimulationService.dll:SimulationDataService"
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue