Merge branch 'master' into httptests

httptests
UbitUmarov 2017-08-16 05:05:57 +01:00
commit 6d4b0a8ce3
36 changed files with 786 additions and 508 deletions

View File

@ -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">

View File

@ -305,17 +305,11 @@ 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;

View File

@ -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;
}
}
}

View File

@ -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; }

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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)
{

View File

@ -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();
m_Scene.AssetService.Store(m_asset);
if (m_asset.FullID != UUID.Zero)
uint perms = ValidateAssets();
if(perms == 0)
{
item.AssetID = m_asset.FullID;
m_Scene.InventoryService.UpdateItem(item);
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);
}
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;
}
m_Scene.AssetService.Store(m_asset);
m_transactions.RemoveXferUploader(m_transactionID);
return true;
}
private void CompleteCreateItem(uint callbackID)
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;

View File

@ -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;
}
}

View File

@ -250,7 +250,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
if (inventoryURL != null && inventoryURL != string.Empty)
{
inventoryURL = inventoryURL.Trim(new char[] { '/' });
m_InventoryURLs[userID] = inventoryURL;
lock (m_InventoryURLs)
m_InventoryURLs[userID] = inventoryURL;
m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Added {0} to the cache of inventory URLs", inventoryURL);
return;
}
@ -268,35 +269,42 @@ 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];
m_InventoryURLs.Remove(userID);
m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Removed {0} from the cache of inventory URLs", url);
}
}
}
public string GetInventoryServiceURL(UUID userID)
{
if (m_InventoryURLs.ContainsKey(userID))
return m_InventoryURLs[userID];
lock (m_InventoryURLs)
{
if (m_InventoryURLs.ContainsKey(userID))
return m_InventoryURLs[userID];
}
CacheInventoryServiceURL(userID);
if (m_InventoryURLs.ContainsKey(userID))
return m_InventoryURLs[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

View File

@ -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,22 +430,25 @@ 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.
WorkManager.RunInThread(o =>
if (shouldStartScripts)
{
Thread.Sleep(15000);
m_log.Info("[ARCHIVER]: Starting scripts in scene objects");
foreach (DearchiveContext sceneContext in sceneContexts.Values)
WorkManager.RunInThread(o =>
{
foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects)
{
sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart
sceneObject.ResumeScripts();
}
Thread.Sleep(15000);
m_log.Info("[ARCHIVER]: Starting scripts in scene objects");
sceneContext.SceneObjects.Clear();
}
}, null, string.Format("ReadArchiveStartScripts (request {0})", m_requestId));
foreach (DearchiveContext sceneContext in sceneContexts.Values)
{
foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects)
{
sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart
sceneObject.ResumeScripts();
}
sceneContext.SceneObjects.Clear();
}
}, null, string.Format("ReadArchiveStartScripts (request {0})", m_requestId));
}
m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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,7 +1883,8 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
public void ClearUpdateSchedule()
{
UpdateFlag = UpdateRequired.NONE;
lock(UpdateFlagLock)
UpdateFlag = UpdateRequired.NONE;
}
/// <summary>
@ -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,30 +3257,21 @@ 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;
ParentGroup.QueueForUpdateCheck(); // just in case
if(UpdateFlag != UpdateRequired.FULL)
{
UpdateFlag = UpdateRequired.FULL;
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}",
// UUID, Name, TimeStampFull);
if (ParentGroup.Scene != null)
ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true);
}
}
else
{
TimeStampFull = (uint)timeNow;
}
UpdateFlag = UpdateRequired.FULL;
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}",
// UUID, Name, TimeStampFull);
if (ParentGroup.Scene != null)
ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true);
}
/// <summary>
@ -3304,21 +3292,23 @@ namespace OpenSim.Region.Framework.Scenes
return;
}
if (UpdateFlag == UpdateRequired.NONE)
lock(UpdateFlagLock)
{
ParentGroup.HasGroupChanged = true;
ParentGroup.QueueForUpdateCheck();
if (UpdateFlag == UpdateRequired.NONE)
{
ParentGroup.HasGroupChanged = true;
ParentGroup.QueueForUpdateCheck();
TimeStampTerse = (uint) Util.UnixTimeSinceEpoch();
UpdateFlag = UpdateRequired.TERSE;
UpdateFlag = UpdateRequired.TERSE;
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}",
// UUID, Name, TimeStampTerse);
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}",
// UUID, Name, TimeStampTerse);
}
if (ParentGroup.Scene != null)
ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false);
}
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
m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset;
m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Util.GetTimeStampMS();
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
m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset;
m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Util.GetTimeStampMS();
lock(UpdateFlagLock)
{
m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset;
m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Util.GetTimeStampMS();
}
if (ParentGroup.IsAttachment)
{
@ -3442,108 +3438,118 @@ namespace OpenSim.Region.Framework.Scenes
/// Tell all the prims which have had updates scheduled
/// </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;
double now = Util.GetTimeStampMS();
Vector3 curvel = Velocity;
Vector3 curacc = Acceleration;
Vector3 angvel = AngularVelocity;
while(true) // just to avoid ugly goto
lock(UpdateFlagLock)
{
double elapsed = now - m_lastUpdateSentTime;
if (elapsed > TIME_MS_TOLERANCE)
break;
double now = Util.GetTimeStampMS();
Vector3 curvel = Velocity;
Vector3 curacc = Acceleration;
Vector3 angvel = AngularVelocity;
if( Math.Abs(curacc.X - m_lastAcceleration.X) > VELOCITY_TOLERANCE ||
Math.Abs(curacc.Y - m_lastAcceleration.Y) > VELOCITY_TOLERANCE ||
Math.Abs(curacc.Z - m_lastAcceleration.Z) > VELOCITY_TOLERANCE)
break;
// velocity change is also direction not only norm)
if( Math.Abs(curvel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE ||
Math.Abs(curvel.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE ||
Math.Abs(curvel.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE)
break;
float vx = Math.Abs(curvel.X);
if(vx > 128.0)
break;
float vy = Math.Abs(curvel.Y);
if(vy > 128.0)
break;
float vz = Math.Abs(curvel.Z);
if(vz > 128.0)
break;
if (
vx < VELOCITY_TOLERANCE &&
vy < VELOCITY_TOLERANCE &&
vz < VELOCITY_TOLERANCE
)
while(true) // just to avoid ugly goto
{
if(!AbsolutePosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
double elapsed = now - m_lastUpdateSentTime;
if (elapsed > TIME_MS_TOLERANCE)
break;
if( Math.Abs(curacc.X - m_lastAcceleration.X) > VELOCITY_TOLERANCE ||
Math.Abs(curacc.Y - m_lastAcceleration.Y) > VELOCITY_TOLERANCE ||
Math.Abs(curacc.Z - m_lastAcceleration.Z) > VELOCITY_TOLERANCE)
break;
// velocity change is also direction not only norm)
if( Math.Abs(curvel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE ||
Math.Abs(curvel.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE ||
Math.Abs(curvel.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE)
break;
float vx = Math.Abs(curvel.X);
if(vx > 128.0)
break;
float vy = Math.Abs(curvel.Y);
if(vy > 128.0)
break;
float vz = Math.Abs(curvel.Z);
if(vz > 128.0)
break;
if (
vx < VELOCITY_TOLERANCE &&
vy < VELOCITY_TOLERANCE &&
vz < VELOCITY_TOLERANCE
)
{
if(!AbsolutePosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
break;
if (vx < 1e-4 &&
vy < 1e-4 &&
vz < 1e-4 &&
(
Math.Abs(m_lastVelocity.X) > 1e-4 ||
Math.Abs(m_lastVelocity.Y) > 1e-4 ||
Math.Abs(m_lastVelocity.Z) > 1e-4
))
if (vx < 1e-4 &&
vy < 1e-4 &&
vz < 1e-4 &&
(
Math.Abs(m_lastVelocity.X) > 1e-4 ||
Math.Abs(m_lastVelocity.Y) > 1e-4 ||
Math.Abs(m_lastVelocity.Z) > 1e-4
))
break;
}
if( Math.Abs(angvel.X - m_lastAngularVelocity.X) > VELOCITY_TOLERANCE ||
Math.Abs(angvel.Y - m_lastAngularVelocity.Y) > VELOCITY_TOLERANCE ||
Math.Abs(angvel.Z - m_lastAngularVelocity.Z) > VELOCITY_TOLERANCE)
break;
// viewer interpolators have a limit of 128m/s
float ax = Math.Abs(angvel.X);
if(ax > 64.0)
break;
float ay = Math.Abs(angvel.Y);
if(ay > 64.0)
break;
float az = Math.Abs(angvel.Z);
if(az > 64.0)
break;
if (
ax < VELOCITY_TOLERANCE &&
ay < VELOCITY_TOLERANCE &&
az < VELOCITY_TOLERANCE &&
!RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)
)
break;
needupdate = false;
break;
}
if( Math.Abs(angvel.X - m_lastAngularVelocity.X) > VELOCITY_TOLERANCE ||
Math.Abs(angvel.Y - m_lastAngularVelocity.Y) > VELOCITY_TOLERANCE ||
Math.Abs(angvel.Z - m_lastAngularVelocity.Z) > VELOCITY_TOLERANCE)
break;
if(needupdate)
{
// viewer interpolators have a limit of 128m/s
float ax = Math.Abs(angvel.X);
if(ax > 64.0)
break;
float ay = Math.Abs(angvel.Y);
if(ay > 64.0)
break;
float az = Math.Abs(angvel.Z);
if(az > 64.0)
break;
if (
ax < VELOCITY_TOLERANCE &&
ay < VELOCITY_TOLERANCE &&
az < VELOCITY_TOLERANCE &&
!RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)
)
break;
needupdate = false;
break;
// Update the "last" values
m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset;
m_lastVelocity = curvel;
m_lastAcceleration = curacc;
m_lastAngularVelocity = angvel;
m_lastUpdateSentTime = now;
}
}
if(needupdate)
{
// Update the "last" values
m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset;
m_lastVelocity = curvel;
m_lastAcceleration = curacc;
m_lastAngularVelocity = angvel;
m_lastUpdateSentTime = now;
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,15 +3572,19 @@ 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;
m_lastRotation = RotationOffset;
m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Util.GetTimeStampMS();
// Update the "last" values
m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset;
m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Util.GetTimeStampMS();
}
ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
{
@ -3588,15 +3597,19 @@ 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;
m_lastRotation = RotationOffset;
m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Util.GetTimeStampMS();
// Update the "last" values
m_lastPosition = AbsolutePosition;
m_lastRotation = RotationOffset;
m_lastVelocity = Velocity;
m_lastAcceleration = Acceleration;
m_lastAngularVelocity = AngularVelocity;
m_lastUpdateSentTime = Util.GetTimeStampMS();
}
if (ParentGroup.IsAttachment)
{

View File

@ -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

View File

@ -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
{

View File

@ -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

View File

@ -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;

View File

@ -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)
{

View File

@ -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)
{
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;
}
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);
m_Enabled = true;
}
CacheExpire = TimeSpan.FromHours(fcache);
lock (diskLock)
if(String.IsNullOrEmpty(cachePath))
doMeshFileCache = false;
if(doMeshFileCache)
{
if(doMeshFileCache && cachePath != "")
if(!checkCache())
{
try
{
if (!Directory.Exists(cachePath))
Directory.CreateDirectory(cachePath);
}
catch
{
doMeshFileCache = false;
doCacheExpire = false;
}
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);
@ -265,7 +173,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
/// <param name="faces"></param>
private void AddSubMesh(OSDMap subMeshData, List<Coord> coords, List<Face> faces)
{
// Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap));
// Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap));
// As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some Mesh Level
// of Detail Blocks (maps) contain just a NoGeometry key to signal there is no
@ -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++)
@ -371,10 +306,10 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
faces.Clear();
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;
}
}
primShape.SculptData = Utils.EmptyBytes;
@ -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;
}
}
}

View File

@ -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))
{

View File

@ -525,7 +525,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
}
[Serializable]
public class list: MarshalByRefObject
public class list
{
private object[] m_data;

View File

@ -395,9 +395,10 @@ namespace OpenSim.Services.HypergridService
{
if(SendAgentGodKillToRegion(UUID.Zero, agentID, guinfo))
{
m_log.InfoFormat(
"[GATEKEEPER SERVICE]: Login failed for {0} {1}, reason: already logged in",
account.FirstName, account.LastName);
if(account != null)
m_log.InfoFormat(
"[GATEKEEPER SERVICE]: Login failed for {0} {1}, reason: already logged in",
account.FirstName, account.LastName);
reason = "You appear to be already logged in on the destination grid " +
"Please wait a a minute or two and retry. " +
"If this takes longer than a few minutes please contact the grid owner.";

View File

@ -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();
}

View File

@ -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);

View File

@ -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

View File

@ -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.