mirror of
https://github.com/opensim/opensim.git
synced 2026-08-06 17:32:42 +08:00
Merge branch 'master' into httptests
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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,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
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user