diff --git a/OpenSim/Framework/LandData.cs b/OpenSim/Framework/LandData.cs index accf52ec44..a9a493d876 100644 --- a/OpenSim/Framework/LandData.cs +++ b/OpenSim/Framework/LandData.cs @@ -697,6 +697,8 @@ namespace OpenSim.Framework landData._mediaLoop = _mediaLoop; landData._obscureMusic = _obscureMusic; landData._obscureMedia = _obscureMedia; + landData._simwideArea = _simwideArea; + landData._simwidePrims = _simwidePrims; landData._parcelAccessList.Clear(); foreach (ParcelManager.ParcelAccessEntry entry in _parcelAccessList) diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs index 6e3d6af57c..40ab76571e 100644 --- a/OpenSim/Region/Application/ConfigurationLoader.cs +++ b/OpenSim/Region/Application/ConfigurationLoader.cs @@ -179,8 +179,10 @@ namespace OpenSim for (int i = 0 ; i < sources.Count ; i++) { if (ReadConfig(sources[i])) + { iniFileExists = true; - AddIncludes(sources); + AddIncludes(sources); + } } if (!iniFileExists) @@ -235,10 +237,19 @@ namespace OpenSim string path = Path.Combine(basepath, chunkWithoutWildcards); path = Path.GetFullPath(path) + chunkWithWildcards; string[] paths = Util.Glob(path); - foreach (string p in paths) + + // If the include path contains no wildcards, then warn the user that it wasn't found. + if (wildcardIndex == -1 && paths.Length == 0) { - if (!sources.Contains(p)) - sources.Add(p); + m_log.WarnFormat("[CONFIG]: Could not find include file {0}", path); + } + else + { + foreach (string p in paths) + { + if (!sources.Contains(p)) + sources.Add(p); + } } } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 5dab1bc35e..2c6795fc3e 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -4333,7 +4333,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP updateMessage.SequenceID = sequence_id; if (landData.SimwideArea > 0) { - updateMessage.SimWideMaxPrims = parcelObjectCapacity; + int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); + updateMessage.SimWideMaxPrims = simulatorCapacity; } else { diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs index 542af25b87..4a42c938d5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs @@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; - private IAssetService m_assetService; +// private IAssetService m_assetService; private bool m_dumpAssetsToFile = false; #region IRegionModuleBase Members @@ -85,7 +85,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets public void RegionLoaded(Scene scene) { - m_assetService = m_scene.RequestModuleInterface(); +// m_assetService = m_scene.RequestModuleInterface(); m_scene.EventManager.OnRegisterCaps += RegisterCaps; } diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 8bf2bf86dd..54b95f7de0 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -53,6 +53,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected bool m_Enabled = false; protected Scene m_aScene; protected List m_agentsInTransit; + private ExpiringCache> m_bannedRegions = + new ExpiringCache>(); + #region ISharedRegionModule @@ -281,6 +284,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } + if (!m_aScene.SimulationService.QueryAccess(finalDestination, sp.ControllingClient.AgentId, Vector3.Zero)) + { + sp.ControllingClient.SendTeleportFailed("The destination region has refused access"); + return; + } + sp.ControllingClient.SendTeleportStart(teleportFlags); // the avatar.Close below will clear the child region list. We need this below for (possibly) @@ -575,7 +584,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #region Agent Crossings - public void Cross(ScenePresence agent, bool isFlying) + public bool Cross(ScenePresence agent, bool isFlying) { Scene scene = agent.Scene; Vector3 pos = agent.AbsolutePosition; @@ -611,6 +620,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } else { + agent.InTransit(); + neighboury = b.TriggerRegionY; neighbourx = b.TriggerRegionX; @@ -620,7 +631,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer agent.ControllingClient.SendAgentAlertMessage( String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false); InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene); - return; + return true; } } @@ -632,6 +643,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } else { + agent.InTransit(); + neighboury = ba.TriggerRegionY; neighbourx = ba.TriggerRegionX; @@ -644,7 +657,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene); - return; + return true; } } @@ -664,6 +677,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } else { + agent.InTransit(); + neighboury = ba.TriggerRegionY; neighbourx = ba.TriggerRegionX; Vector3 newposition = pos; @@ -672,7 +687,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer agent.ControllingClient.SendAgentAlertMessage( String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false); InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene); - return; + return true; } } else if (scene.TestBorderCross(pos + northCross, Cardinals.N)) @@ -694,6 +709,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } else { + agent.InTransit(); + neighboury = b.TriggerRegionY; neighbourx = b.TriggerRegionX; Vector3 newposition = pos; @@ -702,7 +719,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer agent.ControllingClient.SendAgentAlertMessage( String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false); InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene); - return; + return true; } } else if (scene.TestBorderCross(pos + northCross, Cardinals.N)) @@ -738,9 +755,52 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } */ - CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; - d.BeginInvoke(agent, newpos, neighbourx, neighboury, isFlying, CrossAgentToNewRegionCompleted, d); + ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); + int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize); + + ExpiringCache r; + DateTime banUntil; + + if (m_bannedRegions.TryGetValue(agent.ControllingClient.AgentId, out r)) + { + if (r.TryGetValue(neighbourHandle, out banUntil)) + { + if (DateTime.Now < banUntil) + return false; + r.Remove(neighbourHandle); + } + } + else + { + r = null; + } + + GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); + + if (!scene.SimulationService.QueryAccess(neighbourRegion, agent.ControllingClient.AgentId, newpos)) + { + agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel"); + if (r == null) + { + r = new ExpiringCache(); + r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); + + m_bannedRegions.Add(agent.ControllingClient.AgentId, r, TimeSpan.FromSeconds(45)); + } + else + { + r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); + } + return false; + } + + agent.InTransit(); + + CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; + d.BeginInvoke(agent, newpos, neighbourx, neighboury, neighbourRegion, isFlying, CrossAgentToNewRegionCompleted, d); + + return true; } @@ -751,7 +811,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer private void InformClientToInitateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene) { - // This assumes that we know what our neighbors are. + // This assumes that we know what our neighbours are. InformClientToInitateTeleportToLocationDelegate d = InformClientToInitiateTeleportToLocationAsync; d.BeginInvoke(agent, regionX, regionY, position, initiatingScene, @@ -795,21 +855,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer icon.EndInvoke(iar); } - public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, bool isFlying); + public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying); /// - /// This Closes child agents on neighboring regions + /// This Closes child agents on neighbouring regions /// Calls an asynchronous method to do so.. so it doesn't lag the sim. /// - protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, bool isFlying) + protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying) { + ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3}", agent.Firstname, agent.Lastname, neighbourx, neighboury); Scene m_scene = agent.Scene; - ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); - - int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize); - GridRegion neighbourRegion = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y); if (neighbourRegion != null && agent.ValidateAttachments()) { @@ -920,7 +978,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #region Enable Child Agent /// - /// This informs a single neighboring region about agent "avatar". + /// This informs a single neighbouring region about agent "avatar". /// Calls an asynchronous method to do so.. so it doesn't lag the sim. /// public void EnableChildAgent(ScenePresence sp, GridRegion region) @@ -977,7 +1035,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer ScenePresence avatar, AgentCircuitData a, GridRegion reg, IPEndPoint endPoint, bool newAgent); /// - /// This informs all neighboring regions about agent "avatar". + /// This informs all neighbouring regions about agent "avatar". /// Calls an asynchronous method to do so.. so it doesn't lag the sim. /// public void EnableChildAgents(ScenePresence sp) @@ -1108,7 +1166,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer catch (ArgumentOutOfRangeException) { m_log.ErrorFormat( - "[ENTITY TRANSFER MODULE]: Neighbour Regions response included the current region in the neighbor list. The following region will not display to the client: {0} for region {1} ({2}, {3}).", + "[ENTITY TRANSFER MODULE]: Neighbour Regions response included the current region in the neighbour list. The following region will not display to the client: {0} for region {1} ({2}, {3}).", neighbour.ExternalHostName, neighbour.RegionHandle, neighbour.RegionLocX, @@ -1188,7 +1246,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } #endregion - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: {0} is sending {1} EnableSimulator for neighbor region {2} @ {3} " + + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: {0} is sending {1} EnableSimulator for neighbour region {2} @ {3} " + "and EstablishAgentCommunication with seed cap {4}", m_scene.RegionInfo.RegionName, sp.Name, reg.RegionName, reg.RegionHandle, capsPath); diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index cfa41095c8..43de2abd15 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml @@ -14,6 +14,7 @@ + diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index 2dd0099f83..c5972ddf1e 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs @@ -257,18 +257,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation return false; } - public bool QueryAccess(GridRegion destination, UUID id) + public bool QueryAccess(GridRegion destination, UUID id, Vector3 position) { if (destination == null) return false; foreach (Scene s in m_sceneList) { - if (s.RegionInfo.RegionHandle == destination.RegionHandle) - { - //m_log.Debug("[LOCAL COMMS]: Found region to send QueryAccess"); - return s.QueryAccess(id); - } + if (s.RegionInfo.RegionID == destination.RegionID) + return s.QueryAccess(id, position); } //m_log.Debug("[LOCAL COMMS]: region not found for QueryAccess"); return false; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs index 387a9b8133..c4919b319c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs @@ -239,18 +239,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation } - public bool QueryAccess(GridRegion destination, UUID id) + public bool QueryAccess(GridRegion destination, UUID id, Vector3 position) { if (destination == null) return false; // Try local first - if (m_localBackend.QueryAccess(destination, id)) + if (m_localBackend.QueryAccess(destination, id, position)) return true; // else do the remote thing if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) - return m_remoteConnector.QueryAccess(destination, id); + return m_remoteConnector.QueryAccess(destination, id, position); return false; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs index 155335bded..ddef75f616 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs @@ -38,9 +38,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts { private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours! - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = +// LogManager.GetLogger( +// MethodBase.GetCurrentMethod().DeclaringType); + private ExpiringCache m_UUIDCache; private ExpiringCache m_NameCache; diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 3238a8160e..fd8f546737 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -217,22 +217,20 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_scene.DeleteAllSceneObjects(); } - // Try to retain the original creator/owner/lastowner if their uuid is present on this grid - // otherwise, use the master avatar uuid instead + LoadParcels(serialisedParcels); + LoadObjects(serialisedSceneObjects); - // Reload serialized parcels - m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count); - List landData = new List(); - foreach (string serialisedParcel in serialisedParcels) - { - LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); - if (!ResolveUserUuid(parcel.OwnerID)) - parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - landData.Add(parcel); - } - m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData); - m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); + m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); + m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); + } + + /// + /// Load serialized scene objects. + /// + /// + protected void LoadObjects(List serialisedSceneObjects) + { // Reload serialized prims m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); @@ -262,6 +260,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver // to the same scene (when this is possible). sceneObject.ResetIDs(); + // Try to retain the original creator/owner/lastowner if their uuid is present on this grid + // or creator data is present. Otherwise, use the estate owner instead. foreach (SceneObjectPart part in sceneObject.Parts) { if (part.CreatorData == null || part.CreatorData == string.Empty) @@ -318,11 +318,36 @@ namespace OpenSim.Region.CoreModules.World.Archiver int ignoredObjects = serialisedSceneObjects.Count - sceneObjectsLoadedCount; if (ignoredObjects > 0) - m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects); - - m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); - - m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); + m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects); + } + + /// + /// Load serialized parcels. + /// + /// + protected void LoadParcels(List serialisedParcels) + { + // Reload serialized parcels + m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count); + List landData = new List(); + foreach (string serialisedParcel in serialisedParcels) + { + LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); + if (!ResolveUserUuid(parcel.OwnerID)) + parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + +// m_log.DebugFormat( +// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", +// parcel.Name, parcel.LocalID, parcel.Area); + + landData.Add(parcel); + } + + if (!m_merge) + m_scene.LandChannel.Clear(false); + + m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData); + m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); } /// diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index b0563c5ff1..01f04d93d3 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -555,37 +555,12 @@ namespace OpenSim.Region.CoreModules.World.Estate try { + MemoryStream terrainStream = new MemoryStream(terrainData); + terr.LoadFromStream(filename, terrainStream); + terrainStream.Close(); - string localfilename = "terrain.raw"; - - if (terrainData.Length == 851968) - { - localfilename = Path.Combine(Util.dataDir(),"terrain.raw"); // It's a .LLRAW - } - - if (terrainData.Length == 196662) // 24-bit 256x256 Bitmap - localfilename = Path.Combine(Util.dataDir(), "terrain.bmp"); - - if (terrainData.Length == 256 * 256 * 4) // It's a .R32 - localfilename = Path.Combine(Util.dataDir(), "terrain.r32"); - - if (terrainData.Length == 256 * 256 * 8) // It's a .R64 - localfilename = Path.Combine(Util.dataDir(), "terrain.r64"); - - if (File.Exists(localfilename)) - { - File.Delete(localfilename); - } - - FileStream input = new FileStream(localfilename, FileMode.CreateNew); - input.Write(terrainData, 0, terrainData.Length); - input.Close(); - - FileInfo x = new FileInfo(localfilename); - - terr.LoadFromFile(localfilename); - remoteClient.SendAlertMessage("Your terrain was loaded as a ." + x.Extension + " file. It may take a few moments to appear."); - + FileInfo x = new FileInfo(filename); + remoteClient.SendAlertMessage("Your terrain was loaded as a " + x.Extension + " file. It may take a few moments to appear."); } catch (IOException e) { diff --git a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs index 9e27ef07f8..7d990c265c 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs @@ -116,6 +116,12 @@ namespace OpenSim.Region.CoreModules.World.Land return new List(); } + + public void Clear(bool setupDefaultParcel) + { + if (m_landManagementModule != null) + m_landManagementModule.Clear(setupDefaultParcel); + } public List ParcelsNearPoint(Vector3 position) { diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 70767f7b4c..98ba8c3c8c 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -298,13 +298,19 @@ namespace OpenSim.Region.CoreModules.World.Land m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; m_landIDList.Initialize(); } - + } + + /// + /// Create a default parcel that spans the entire region and is owned by the estate owner. + /// + /// The parcel created. + protected ILandObject CreateDefaultParcel() + { ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); - fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); - AddLandObject(fullSimParcel); + return AddLandObject(fullSimParcel); } public List AllParcels() @@ -577,15 +583,6 @@ namespace OpenSim.Region.CoreModules.World.Land } } - /// - /// Creates a basic Parcel object without an owner (a zeroed key) - /// - /// - public ILandObject CreateBaseLand() - { - return new LandObject(UUID.Zero, false, m_scene); - } - /// /// Adds a land object to the stored list and adds them to the landIDList to what they own /// @@ -645,6 +642,28 @@ namespace OpenSim.Region.CoreModules.World.Land m_landList.Remove(local_id); } } + + /// + /// Clear the scene of all parcels + /// + public void Clear(bool setupDefaultParcel) + { + lock (m_landList) + { + foreach (ILandObject lo in m_landList.Values) + { + //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID); + m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID); + } + + m_landList.Clear(); + } + + ResetSimLandObjects(); + + if (setupDefaultParcel) + CreateDefaultParcel(); + } private void performFinalLandJoin(ILandObject master, ILandObject slave) { @@ -690,7 +709,7 @@ namespace OpenSim.Region.CoreModules.World.Land int x; int y; - if (x_float > Constants.RegionSize || x_float <= 0 || y_float > Constants.RegionSize || y_float <= 0) + if (x_float >= Constants.RegionSize || x_float < 0 || y_float >= Constants.RegionSize || y_float < 0) return null; try @@ -732,10 +751,10 @@ namespace OpenSim.Region.CoreModules.World.Land { try { - if (m_landList.ContainsKey(m_landIDList[x / 4, y / 4])) + //if (m_landList.ContainsKey(m_landIDList[x / 4, y / 4])) return m_landList[m_landIDList[x / 4, y / 4]]; - else - return null; + //else + // return null; } catch (IndexOutOfRangeException) { @@ -1311,7 +1330,6 @@ namespace OpenSim.Region.CoreModules.World.Land } } - void ClientOnParcelDeedToGroup(int parcelLocalID, UUID groupID, IClientAPI remote_client) { ILandObject land; @@ -1327,10 +1345,8 @@ namespace OpenSim.Region.CoreModules.World.Land { land.DeedToGroup(groupID); } - } - #region Land Object From Storage Functions public void EventManagerOnIncomingLandDataFromStorage(List data) @@ -1365,6 +1381,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void EventManagerOnNoLandDataFromStorage() { ResetSimLandObjects(); + CreateDefaultParcel(); } #endregion @@ -1622,14 +1639,36 @@ namespace OpenSim.Region.CoreModules.World.Land protected void InstallInterfaces() { - Command showCommand = - new Command("show", CommandIntentions.COMMAND_STATISTICAL, ShowParcelsCommand, "Shows all parcels on the current region."); + Command clearCommand + = new Command("clear", CommandIntentions.COMMAND_HAZARDOUS, ClearCommand, "Clears all the parcels from the region."); + Command showCommand + = new Command("show", CommandIntentions.COMMAND_STATISTICAL, ShowParcelsCommand, "Shows all parcels on the region."); + m_commander.RegisterCommand("clear", clearCommand); m_commander.RegisterCommand("show", showCommand); // Add this to our scene so scripts can call these functions m_scene.RegisterModuleCommander(m_commander); - } + } + + protected void ClearCommand(Object[] args) + { + string response = MainConsole.Instance.CmdPrompt( + string.Format( + "Are you sure that you want to clear all land parcels from {0} (y or n)", + m_scene.RegionInfo.RegionName), + "n"); + + if (response.ToLower() == "y") + { + Clear(true); + MainConsole.Instance.OutputFormat("Cleared all parcels from {0}", m_scene.RegionInfo.RegionName); + } + else + { + MainConsole.Instance.OutputFormat("Aborting clear of all parcels from {0}", m_scene.RegionInfo.RegionName); + } + } protected void ShowParcelsCommand(Object[] args) { @@ -1637,8 +1676,9 @@ namespace OpenSim.Region.CoreModules.World.Land report.AppendFormat("Land information for {0}\n", m_scene.RegionInfo.RegionName); report.AppendFormat( - "{0,-20} {1,-9} {2,-18} {3,-18} {4,-20}\n", + "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n", "Parcel Name", + "Local ID", "Area", "Starts", "Ends", @@ -1651,12 +1691,12 @@ namespace OpenSim.Region.CoreModules.World.Land LandData ld = lo.LandData; report.AppendFormat( - "{0,-20} {1,-9} {2,-18} {3,-18} {4,-20}\n", - ld.Name, ld.Area, lo.StartPoint, lo.EndPoint, m_userManager.GetUserName(ld.OwnerID)); + "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n", + ld.Name, ld.LocalID, ld.Area, lo.StartPoint, lo.EndPoint, m_userManager.GetUserName(ld.OwnerID)); } } MainConsole.Instance.Output(report.ToString()); - } + } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index b90e3078e2..46c15ed2c3 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -66,6 +66,13 @@ namespace OpenSim.Region.CoreModules.World.Land #region ILandObject Members + public int GetPrimsFree() + { + m_scene.EventManager.TriggerParcelPrimCountUpdate(); + int free = GetSimulatorMaxPrimCount(this) - m_landData.SimwidePrims; + return free; + } + public LandData LandData { get { return m_landData; } @@ -141,7 +148,7 @@ namespace OpenSim.Region.CoreModules.World.Land /// Returns true if the piece of land contains the specified point public bool ContainsPoint(int x, int y) { - if (x >= 0 && y >= 0 && x <= Constants.RegionSize && y <= Constants.RegionSize) + if (x >= 0 && y >= 0 && x < Constants.RegionSize && y < Constants.RegionSize) { return (LandBitmap[x / 4, y / 4] == true); } @@ -183,7 +190,11 @@ namespace OpenSim.Region.CoreModules.World.Land else { // Normal Calculations - return (int)Math.Round(((float)LandData.Area / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); + int parcelMax = (int)(((float)LandData.Area / 65536.0f) + * (float)m_scene.RegionInfo.ObjectCapacity + * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); + // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL! + return parcelMax; } } public int GetSimulatorMaxPrimCount(ILandObject thisObject) @@ -195,7 +206,9 @@ namespace OpenSim.Region.CoreModules.World.Land else { //Normal Calculations - return m_scene.RegionInfo.ObjectCapacity; + int simMax = (int)(((float)LandData.SimwideArea / 65536.0f) + * (float)m_scene.RegionInfo.ObjectCapacity); + return simMax; } } #endregion @@ -369,7 +382,7 @@ namespace OpenSim.Region.CoreModules.World.Land newData.AuthBuyerID = UUID.Zero; newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); - + m_scene.EventManager.TriggerParcelPrimCountUpdate(); SendLandUpdateToAvatarsOverMe(true); } @@ -384,7 +397,7 @@ namespace OpenSim.Region.CoreModules.World.Land newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); - + m_scene.EventManager.TriggerParcelPrimCountUpdate(); SendLandUpdateToAvatarsOverMe(true); } @@ -450,6 +463,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client) { + m_scene.EventManager.TriggerParcelPrimCountUpdate(); SendLandProperties(0, snap_selection, 0, remote_client); } diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs new file mode 100644 index 0000000000..34ef67f10b --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs @@ -0,0 +1,406 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Land +{ + public class ParcelCounts + { + public int Owner = 0; + public int Group = 0; + public int Others = 0; + public Dictionary Users = + new Dictionary (); + } + + public class PrimCountModule : IPrimCountModule, INonSharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_Scene; + private Dictionary m_PrimCounts = + new Dictionary(); + private Dictionary m_OwnerMap = + new Dictionary(); + private Dictionary m_SimwideCounts = + new Dictionary(); + private Dictionary m_ParcelCounts = + new Dictionary(); + + // For now, a simple simwide taint to get this up. Later parcel based + // taint to allow recounting a parcel if only ownership has changed + // without recounting the whole sim. + private bool m_Tainted = true; + private Object m_TaintLock = new Object(); + + public Type ReplaceableInterface + { + get { return null; } + } + + public void Initialise(IConfigSource source) + { + } + + public void AddRegion(Scene scene) + { + m_Scene = scene; + + m_Scene.EventManager.OnParcelPrimCountAdd += + OnParcelPrimCountAdd; + m_Scene.EventManager.OnObjectBeingRemovedFromScene += + OnObjectBeingRemovedFromScene; + m_Scene.EventManager.OnParcelPrimCountTainted += + OnParcelPrimCountTainted; + } + + public void RegionLoaded(Scene scene) + { + } + + public void RemoveRegion(Scene scene) + { + } + + public void Close() + { + } + + public string Name + { + get { return "PrimCountModule"; } + } + + private void OnParcelPrimCountAdd(SceneObjectGroup obj) + { + // If we're tainted already, don't bother to add. The next + // access will cause a recount anyway + lock (m_TaintLock) + { + if (!m_Tainted) + AddObject(obj); + } + } + + private void OnObjectBeingRemovedFromScene(SceneObjectGroup obj) + { + // Don't bother to update tainted counts + lock (m_TaintLock) + { + if (!m_Tainted) + RemoveObject(obj); + } + } + + private void OnParcelPrimCountTainted() + { + lock (m_TaintLock) + m_Tainted = true; + } + + public void TaintPrimCount(ILandObject land) + { + lock (m_TaintLock) + m_Tainted = true; + } + + public void TaintPrimCount(int x, int y) + { + lock (m_TaintLock) + m_Tainted = true; + } + + public void TaintPrimCount() + { + lock (m_TaintLock) + m_Tainted = true; + } + + // NOTE: Call under Taint Lock + private void AddObject(SceneObjectGroup obj) + { + if (obj.IsAttachment) + return; + if (((obj.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)) + return; + + Vector3 pos = obj.AbsolutePosition; + ILandObject landObject = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); + LandData landData = landObject.LandData; + + ParcelCounts parcelCounts; + if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts)) + { + UUID landOwner = landData.OwnerID; + int partCount = obj.Parts.Length; + + m_SimwideCounts[landOwner] += partCount; + if (parcelCounts.Users.ContainsKey(obj.OwnerID)) + parcelCounts.Users[obj.OwnerID] += partCount; + else + parcelCounts.Users[obj.OwnerID] = partCount; + + if (landData.IsGroupOwned) + { + if (obj.OwnerID == landData.GroupID) + parcelCounts.Owner += partCount; + else if (obj.GroupID == landData.GroupID) + parcelCounts.Group += partCount; + else + parcelCounts.Others += partCount; + } + else + { + if (obj.OwnerID == landData.OwnerID) + parcelCounts.Owner += partCount; + else if (obj.GroupID == landData.GroupID) + parcelCounts.Group += partCount; + else + parcelCounts.Others += partCount; + } + } + } + + // NOTE: Call under Taint Lock + private void RemoveObject(SceneObjectGroup obj) + { + } + + public IPrimCounts GetPrimCounts(UUID parcelID) + { + PrimCounts primCounts; + + lock (m_PrimCounts) + { + if (m_PrimCounts.TryGetValue(parcelID, out primCounts)) + return primCounts; + + primCounts = new PrimCounts(parcelID, this); + m_PrimCounts[parcelID] = primCounts; + } + return primCounts; + } + + public int GetOwnerCount(UUID parcelID) + { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + ParcelCounts counts; + if (m_ParcelCounts.TryGetValue(parcelID, out counts)) + return counts.Owner; + } + return 0; + } + + public int GetGroupCount(UUID parcelID) + { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + ParcelCounts counts; + if (m_ParcelCounts.TryGetValue(parcelID, out counts)) + return counts.Group; + } + return 0; + } + + public int GetOthersCount(UUID parcelID) + { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + ParcelCounts counts; + if (m_ParcelCounts.TryGetValue(parcelID, out counts)) + return counts.Others; + } + return 0; + } + + public int GetSimulatorCount(UUID parcelID) + { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + UUID owner; + if (m_OwnerMap.TryGetValue(parcelID, out owner)) + { + int val; + if (m_SimwideCounts.TryGetValue(owner, out val)) + return val; + } + } + return 0; + } + + public int GetUserCount(UUID parcelID, UUID userID) + { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + ParcelCounts counts; + if (m_ParcelCounts.TryGetValue(parcelID, out counts)) + { + int val; + if (counts.Users.TryGetValue(userID, out val)) + return val; + } + } + return 0; + } + + // NOTE: This method MUST be called while holding the taint lock! + private void Recount() + { + m_OwnerMap.Clear(); + m_SimwideCounts.Clear(); + m_ParcelCounts.Clear(); + + List land = m_Scene.LandChannel.AllParcels(); + + foreach (ILandObject l in land) + { + LandData landData = l.LandData; + + m_OwnerMap[landData.GlobalID] = landData.OwnerID; + m_SimwideCounts[landData.OwnerID] = 0; + m_ParcelCounts[landData.GlobalID] = new ParcelCounts(); + } + + m_Scene.ForEachSOG(AddObject); + + List primcountKeys = new List(m_PrimCounts.Keys); + foreach (UUID k in primcountKeys) + { + if (!m_OwnerMap.ContainsKey(k)) + m_PrimCounts.Remove(k); + } + m_Tainted = false; + } + } + + public class PrimCounts : IPrimCounts + { + private PrimCountModule m_Parent; + private UUID m_ParcelID; + private UserPrimCounts m_UserPrimCounts; + + public PrimCounts (UUID parcelID, PrimCountModule parent) + { + m_ParcelID = parcelID; + m_Parent = parent; + + m_UserPrimCounts = new UserPrimCounts(this); + } + + public int Owner + { + get + { + return m_Parent.GetOwnerCount(m_ParcelID); + } + } + + public int Group + { + get + { + return m_Parent.GetGroupCount(m_ParcelID); + } + } + + public int Others + { + get + { + return m_Parent.GetOthersCount(m_ParcelID); + } + } + + public int Simulator + { + get + { + return m_Parent.GetSimulatorCount(m_ParcelID); + } + } + + public IUserPrimCounts Users + { + get + { + return m_UserPrimCounts; + } + } + + public int GetUserCount(UUID userID) + { + return m_Parent.GetUserCount(m_ParcelID, userID); + } + } + + public class UserPrimCounts : IUserPrimCounts + { + private PrimCounts m_Parent; + + public UserPrimCounts(PrimCounts parent) + { + m_Parent = parent; + } + + public int this[UUID userID] + { + get + { + return m_Parent.GetUserCount(userID); + } + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs index c65aa6a8bd..ab6a598ace 100644 --- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs +++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs @@ -45,8 +45,8 @@ namespace OpenSim.Region.CoreModules.World.Region [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RestartModule")] public class RestartModule : INonSharedRegionModule, IRestartModule { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = +// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected Scene m_Scene; protected Timer m_CountdownTimer = null; diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs index 3ee20ae48f..2919897153 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs @@ -30,6 +30,7 @@ using System.IO; using System.Text; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Framework; namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders { @@ -53,17 +54,120 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders return retval; } + public ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight) + { + TerrainChannel retval = new TerrainChannel(sectionWidth, sectionHeight); + + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Open, FileAccess.Read); + BinaryReader bs = new BinaryReader(s); + + bool eof = false; + + int fileXPoints = 0; + int fileYPoints = 0; + + // Terragen file + while (eof == false) + { + string tmp = Encoding.ASCII.GetString(bs.ReadBytes(4)); + switch (tmp) + { + case "SIZE": + fileXPoints = bs.ReadInt16() + 1; + fileYPoints = fileXPoints; + bs.ReadInt16(); + break; + case "XPTS": + fileXPoints = bs.ReadInt16(); + bs.ReadInt16(); + break; + case "YPTS": + fileYPoints = bs.ReadInt16(); + bs.ReadInt16(); + break; + case "ALTW": + eof = true; + Int16 heightScale = bs.ReadInt16(); + Int16 baseHeight = bs.ReadInt16(); + + int currFileYOffset = 0; + + // if our region isn't on the first X section of the areas to be landscaped, then + // advance to our section of the file + while (currFileYOffset < offsetY) + { + // read a whole strip of regions + int heightsToRead = sectionHeight * fileXPoints; + bs.ReadBytes(heightsToRead * 2); // because the shorts are 2 bytes in the file + currFileYOffset++; + } + + for (int y = 0; y < sectionHeight; y++) + { + int currFileXOffset = 0; + + // if our region isn't the first X section of the areas to be landscaped, then + // advance the stream to the X start pos of our section in the file + // i.e. eat X upto where we start + while (currFileXOffset < offsetX) + { + bs.ReadBytes(sectionWidth * 2); // 2 bytes = short + currFileXOffset++; + } + + // got to our X offset, so write our regions X line + for (int x = 0; x < sectionWidth; x++) + { + // Read a strip and continue + retval[x, y] = baseHeight + bs.ReadInt16() * (double)heightScale / 65536.0; + } + // record that we wrote it + currFileXOffset++; + + // if our region isn't the last X section of the areas to be landscaped, then + // advance the stream to the end of this Y column + while (currFileXOffset < fileWidth) + { + // eat the next regions x line + bs.ReadBytes(sectionWidth * 2); // 2 bytes = short + currFileXOffset++; + } + //eat the last additional point + bs.ReadInt16(); + } + + + break; + default: + bs.ReadInt32(); + break; + } + } + + bs.Close(); + s.Close(); + + return retval; + } + public ITerrainChannel LoadStream(Stream s) { - TerrainChannel retval = new TerrainChannel(); + + int w = (int)Constants.RegionSize; + int h = (int)Constants.RegionSize; + + TerrainChannel retval = new TerrainChannel(w, h); BinaryReader bs = new BinaryReader(s); bool eof = false; if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ") { - int w = 256; - int h = 256; + + int fileWidth = w; + int fileHeight = h; + // Terragen file while (eof == false) @@ -73,30 +177,27 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders { case "SIZE": int sztmp = bs.ReadInt16() + 1; - w = sztmp; - h = sztmp; + fileWidth = sztmp; + fileHeight = sztmp; bs.ReadInt16(); break; case "XPTS": - w = bs.ReadInt16(); + fileWidth = bs.ReadInt16(); bs.ReadInt16(); break; case "YPTS": - h = bs.ReadInt16(); + fileHeight = bs.ReadInt16(); bs.ReadInt16(); break; case "ALTW": eof = true; Int16 heightScale = bs.ReadInt16(); Int16 baseHeight = bs.ReadInt16(); - retval = new TerrainChannel(w, h); - int x; - for (x = 0; x < w; x++) + for (int y = 0; y < h; y++) { - int y; - for (y = 0; y < h; y++) + for (int x = 0; x < w; x++) { - retval[x, y] = baseHeight + bs.ReadInt16() * (double) heightScale / 65536.0; + retval[x, y] = baseHeight + bs.ReadInt16() * (double)heightScale / 65536.0; } } break; @@ -114,12 +215,92 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders public void SaveFile(string filename, ITerrainChannel map) { - throw new NotImplementedException(); + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Create, FileAccess.Write); + SaveStream(s, map); + + s.Close(); } public void SaveStream(Stream stream, ITerrainChannel map) { - throw new NotImplementedException(); + BinaryWriter bs = new BinaryWriter(stream); + + //find the max and min heights on the map + double heightMax = map[0,0]; + double heightMin = map[0,0]; + + for (int y = 0; y < map.Height; y++) + { + for (int x = 0; x < map.Width; x++) + { + double current = map[x,y]; + if (heightMax < current) + heightMax = current; + if (heightMin > current) + heightMin = current; + } + } + + double baseHeight = Math.Floor( (heightMax + heightMin) / 2d ); + + double horizontalScale = Math.Ceiling((heightMax - heightMin)); + + // if we are completely flat add 1cm range to avoid NaN divisions + if (horizontalScale < 0.01d) + horizontalScale = 0.01d; + + System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + + bs.Write(enc.GetBytes("TERRAGENTERRAIN ")); + + bs.Write(enc.GetBytes("SIZE")); + bs.Write(Convert.ToInt16(Constants.RegionSize)); + bs.Write(Convert.ToInt16(0)); // necessary padding + + //The XPTS and YPTS chunks are not needed for square regions + //but L3DT won't load the terrain file properly without them. + bs.Write(enc.GetBytes("XPTS")); + bs.Write(Convert.ToInt16(Constants.RegionSize)); + bs.Write(Convert.ToInt16(0)); // necessary padding + + bs.Write(enc.GetBytes("YPTS")); + bs.Write(Convert.ToInt16(Constants.RegionSize)); + bs.Write(Convert.ToInt16(0)); // necessary padding + + bs.Write(enc.GetBytes("SCAL")); + bs.Write(ToLittleEndian(1f)); //we're going to say that 1 terrain unit is 1 metre + bs.Write(ToLittleEndian(1f)); + bs.Write(ToLittleEndian(1f)); + + // as we are square and not projected on a sphere then the other + // header blocks are not required + + // now write the elevation data + bs.Write(enc.GetBytes("ALTW")); + bs.Write(Convert.ToInt16(horizontalScale)); // range between max and min + bs.Write(Convert.ToInt16(baseHeight)); // base height or mid point + + for (int y = 0; y < map.Height; y++) + { + for (int x = 0; x < map.Width; x++) + { + float elevation = (float)((map[x,y] - baseHeight) * 65536 ) / (float)horizontalScale; // see LoadStream for inverse + + // clamp rounding issues + if (elevation > Int16.MaxValue) + elevation = Int16.MaxValue; + else if (elevation < Int16.MinValue) + elevation = Int16.MinValue; + + bs.Write(Convert.ToInt16(elevation)); + } + } + + //This is only necessary for older versions of Terragen. + bs.Write(enc.GetBytes("EOF ")); + + bs.Close(); } public string FileExtension @@ -127,16 +308,34 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders get { return ".ter"; } } - public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h) - { - throw new NotImplementedException(); - } - #endregion public override string ToString() { return "Terragen"; } + + /// + /// terragen SCAL floats need to be written intel ordered regardless of + /// big or little endian system + /// + /// + /// + private byte[] ToLittleEndian( float number) + { + byte[] retVal = BitConverter.GetBytes(number); + if (BitConverter.IsLittleEndian == false) + { + byte[] tmp = new byte[4]; + for (int i = 0; i < 4; i++) + { + tmp[i] = retVal[3 - i]; + } + retVal = tmp; + + } + return retVal ; + } + } } diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 25d73c2c0f..8a79d78b22 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -131,7 +131,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_scene.EventManager.OnNewClient += EventManager_OnNewClient; m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick; - InstallInterfaces(); } InstallDefaultEffects(); @@ -140,6 +139,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain public void RegionLoaded(Scene scene) { + //Do this here to give file loaders time to initialize and + //register their supported file extensions and file formats. + InstallInterfaces(); } public void RemoveRegion(Scene scene) @@ -1082,8 +1084,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain { // Load / Save string supportedFileExtensions = ""; + string supportedFilesSeparator = ""; foreach (KeyValuePair loader in m_loaders) - supportedFileExtensions += " " + loader.Key + " (" + loader.Value + ")"; + { + supportedFileExtensions += supportedFilesSeparator + loader.Key + " (" + loader.Value + ")"; + supportedFilesSeparator = ", "; + } Command loadFromFileCommand = new Command("load", CommandIntentions.COMMAND_HAZARDOUS, InterfaceLoadFile, "Loads a terrain from a specified file."); diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs index e8738c465e..8b96de46fd 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs @@ -42,7 +42,7 @@ namespace OpenSim.Region.Framework.Interfaces void TeleportHome(UUID id, IClientAPI client); - void Cross(ScenePresence agent, bool isFlying); + bool Cross(ScenePresence agent, bool isFlying); void AgentArrivedAtDestination(UUID agent); diff --git a/OpenSim/Region/Framework/Interfaces/ILandChannel.cs b/OpenSim/Region/Framework/Interfaces/ILandChannel.cs index 20b8ab6b6d..30bae16d81 100644 --- a/OpenSim/Region/Framework/Interfaces/ILandChannel.cs +++ b/OpenSim/Region/Framework/Interfaces/ILandChannel.cs @@ -69,6 +69,14 @@ namespace OpenSim.Region.Framework.Interfaces /// ILandObject GetLandObject(int localID); + /// + /// Clear the land channel of all parcels. + /// + /// + /// If true, set up a default parcel covering the whole region owned by the estate owner. + /// + void Clear(bool setupDefaultParcel); + bool IsLandPrimCountTainted(); bool IsForcefulBansAllowed(); void UpdateLandObject(int localID, LandData data); diff --git a/OpenSim/Region/Framework/Interfaces/ILandObject.cs b/OpenSim/Region/Framework/Interfaces/ILandObject.cs index 576b645b0e..eeb9d3ad1d 100644 --- a/OpenSim/Region/Framework/Interfaces/ILandObject.cs +++ b/OpenSim/Region/Framework/Interfaces/ILandObject.cs @@ -39,6 +39,7 @@ namespace OpenSim.Region.Framework.Interfaces { int GetParcelMaxPrimCount(ILandObject thisObject); int GetSimulatorMaxPrimCount(ILandObject thisObject); + int GetPrimsFree(); LandData LandData { get; set; } bool[,] LandBitmap { get; set; } diff --git a/OpenSim/Region/Framework/Interfaces/IPrimCountModule.cs b/OpenSim/Region/Framework/Interfaces/IPrimCountModule.cs new file mode 100644 index 0000000000..65158e1c80 --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IPrimCountModule.cs @@ -0,0 +1,55 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Region.Framework.Interfaces +{ + public interface IPrimCountModule + { + void TaintPrimCount(ILandObject land); + void TaintPrimCount(int x, int y); + void TaintPrimCount(); + + IPrimCounts GetPrimCounts(UUID parcelID); + } + + public interface IPrimCounts + { + int Owner { get; } + int Group { get; } + int Others { get; } + int Simulator { get; } + IUserPrimCounts Users { get; } + } + + public interface IUserPrimCounts + { + int this[UUID agentID] { get; } + } +} diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index dc08b4954c..4fca2610d2 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3861,14 +3861,16 @@ namespace OpenSim.Region.Framework.Scenes RequestTeleportLocation(remoteClient, info.RegionHandle, position, Vector3.Zero, (uint)(TPFlags.SetLastToTarget | TPFlags.ViaLandmark)); } - public void CrossAgentToNewRegion(ScenePresence agent, bool isFlying) + public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying) { if (m_teleportModule != null) - m_teleportModule.Cross(agent, isFlying); + return m_teleportModule.Cross(agent, isFlying); else { m_log.DebugFormat("[SCENE]: Unable to cross agent to neighbouring region, because there is no AgentTransferModule"); } + + return false; } public void SendOutChildAgentUpdates(AgentPosition cadu, ScenePresence presence) @@ -4919,7 +4921,7 @@ namespace OpenSim.Region.Framework.Scenes // from logging into the region, teleporting into the region // or corssing the broder walking, but will NOT prevent // child agent creation, thereby emulating the SL behavior. - public bool QueryAccess(UUID agentID) + public bool QueryAccess(UUID agentID, Vector3 position) { return true; } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 1c276fa87f..cd70de8440 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2725,29 +2725,57 @@ namespace OpenSim.Region.Framework.Scenes // Makes sure avatar does not end up outside region if (neighbor <= 0) { - if (!needsTransit) + if (needsTransit) { if (m_requestedSitTargetUUID == UUID.Zero) { + bool isFlying = m_physicsActor.Flying; + RemoveFromPhysicalScene(); + Vector3 pos = AbsolutePosition; if (AbsolutePosition.X < 0) - pos.X += Velocity.X; + pos.X += Velocity.X * 2; else if (AbsolutePosition.X > Constants.RegionSize) - pos.X -= Velocity.X; + pos.X -= Velocity.X * 2; if (AbsolutePosition.Y < 0) - pos.Y += Velocity.Y; + pos.Y += Velocity.Y * 2; else if (AbsolutePosition.Y > Constants.RegionSize) - pos.Y -= Velocity.Y; + pos.Y -= Velocity.Y * 2; + Velocity = Vector3.Zero; AbsolutePosition = pos; + + AddToPhysicalScene(isFlying); } } } else if (neighbor > 0) - CrossToNewRegion(); + { + if (!CrossToNewRegion()) + { + if (m_requestedSitTargetUUID == UUID.Zero) + { + bool isFlying = m_physicsActor.Flying; + RemoveFromPhysicalScene(); + + Vector3 pos = AbsolutePosition; + if (AbsolutePosition.X < 0) + pos.X += Velocity.X * 2; + else if (AbsolutePosition.X > Constants.RegionSize) + pos.X -= Velocity.X * 2; + if (AbsolutePosition.Y < 0) + pos.Y += Velocity.Y * 2; + else if (AbsolutePosition.Y > Constants.RegionSize) + pos.Y -= Velocity.Y * 2; + Velocity = Vector3.Zero; + AbsolutePosition = pos; + + AddToPhysicalScene(isFlying); + } + } + } } else { - RemoveFromPhysicalScene(); // This constant has been inferred from experimentation // I'm not sure what this value should be, so I tried a few values. timeStep = 0.04f; @@ -2796,16 +2824,15 @@ namespace OpenSim.Region.Framework.Scenes /// If the neighbor accepts, remove the agent's viewable avatar from this scene /// set them to a child agent. /// - protected void CrossToNewRegion() + protected bool CrossToNewRegion() { - InTransit(); try { - m_scene.CrossAgentToNewRegion(this, m_physicsActor.Flying); + return m_scene.CrossAgentToNewRegion(this, m_physicsActor.Flying); } catch { - m_scene.CrossAgentToNewRegion(this, false); + return m_scene.CrossAgentToNewRegion(this, false); } } diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs index be5411a34b..98e5453d1e 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs @@ -62,6 +62,11 @@ public class RegionCombinerLargeLandChannel : ILandChannel { return RootRegionLandChannel.AllParcels(); } + + public void Clear(bool setupDefaultParcel) + { + RootRegionLandChannel.Clear(setupDefaultParcel); + } public ILandObject GetLandObject(int x, int y) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index bca08fb771..c0c790dd28 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -702,7 +702,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // and convert the regionName to the target region if (regionName.Contains(".") && regionName.Contains(":")) { - List regions = World.GridService.GetRegionsByName(World.RegionInfo.ScopeID, regionName, 1); +// List regions = World.GridService.GetRegionsByName(World.RegionInfo.ScopeID, regionName, 1); string[] parts = regionName.Split(new char[] { ':' }); if (parts.Length > 2) regionName = parts[0] + ':' + parts[1] + "/ " + parts[2]; diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs index 57672a815f..2601d2ac5a 100644 --- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs +++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs @@ -326,10 +326,17 @@ namespace OpenSim.Server.Handlers.Simulation return; } + // m_log.DebugFormat("[AGENT HANDLER]: Received QUERYACCESS with {0}", (string)request["body"]); + OSDMap args = Utils.GetOSDMap((string)request["body"]); + + Vector3 position = Vector3.Zero; + if (args.ContainsKey("position")) + position = Vector3.Parse(args["position"].AsString()); + GridRegion destination = new GridRegion(); destination.RegionID = regionID; - bool result = m_SimulationService.QueryAccess(destination, id); + bool result = m_SimulationService.QueryAccess(destination, id, position); responsedata["int_response_code"] = HttpStatusCode.OK; responsedata["str_response_string"] = result.ToString(); diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 143c2968a3..c5313fc8b9 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -31,6 +31,7 @@ using System.IO; using System.Net; using System.Reflection; using System.Text; +using System.Collections; using OpenSim.Framework; using OpenSim.Services.Interfaces; @@ -206,9 +207,9 @@ namespace OpenSim.Services.Connectors.Simulation /// /// - public bool QueryAccess(GridRegion destination, UUID id) + public bool QueryAccess(GridRegion destination, UUID id, Vector3 position) { - // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess start"); + // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess start, position={0}", position); IPEndPoint ext = destination.ExternalEndPoint; if (ext == null) return false; @@ -216,10 +217,26 @@ namespace OpenSim.Services.Connectors.Simulation // Eventually, we want to use a caps url instead of the agentID string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + OSDMap request = new OSDMap(); + request.Add("position", OSD.FromString(position.ToString())); + try { - OSDMap result = WebUtil.ServiceOSDRequest(uri,null,"QUERYACCESS",10000); - return result["Success"].AsBoolean(); + OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 10000); + bool success = result["Success"].AsBoolean(); + if (!success) + { + if (result.ContainsKey("Message")) + { + string message = result["Message"].AsString(); + if (message == "Service request failed: [MethodNotAllowed] MethodNotAllowed") // Old style region + { + m_log.Info("[REMOTE SIMULATION CONNECTOR]: The above web util error was caused by a TP to a sim that doesn't support QUERYACCESS and can be ignored"); + return true; + } + } + } + return success; } catch (Exception e) { diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs index 12e898202e..48a2185b62 100644 --- a/OpenSim/Services/Interfaces/ISimulationService.cs +++ b/OpenSim/Services/Interfaces/ISimulationService.cs @@ -60,7 +60,7 @@ namespace OpenSim.Services.Interfaces bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent); - bool QueryAccess(GridRegion destination, UUID id); + bool QueryAccess(GridRegion destination, UUID id, Vector3 position); /// /// Message from receiving region to departing region, telling it got contacted by the client. diff --git a/OpenSim/Tests/Common/Mock/TestLandChannel.cs b/OpenSim/Tests/Common/Mock/TestLandChannel.cs index 159764cff8..c3134b3bc1 100644 --- a/OpenSim/Tests/Common/Mock/TestLandChannel.cs +++ b/OpenSim/Tests/Common/Mock/TestLandChannel.cs @@ -55,6 +55,11 @@ namespace OpenSim.Tests.Common.Mock { return new List(); } + + public void Clear(bool setupDefaultParcel) + { + // Intentionally blank since we don't save any parcel data in the test channel + } protected ILandObject GetNoLand() { diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 90284530f4..475d4a0c53 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1186,6 +1186,11 @@ ; This makes the Groups modules very chatty on the console. DebugEnabled = false + ; Groups data is cached for this number of seconds before another request is made to the groups service + ; Set to 0 to disable the cache. + ; Default is 30 seconds + GroupsCacheTimeout = 30 + ; Specify which messaging module to use for groups messaging and if it's enabled ;MessagingModule = GroupsMessagingModule ;MessagingEnabled = true