/* * 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.IO; using System.Linq; using System.Reflection; using System.Security; using System.Timers; using log4net; using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using RegionFlags = OpenMetaverse.RegionFlags; namespace OpenSim.Region.CoreModules.World.Estate { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EstateManagementModule")] public class EstateManagementModule : IEstateModule, INonSharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Timer m_regionChangeTimer = new Timer(); public Scene Scene { get; private set; } public IUserManagement UserManager { get; private set; } protected EstateManagementCommands m_commands; /// /// If false, region restart requests from the client are blocked even if they are otherwise legitimate. /// public bool AllowRegionRestartFromClient { get; set; } private EstateTerrainXferHandler TerrainUploader; public TelehubManager m_Telehub; public event ChangeDelegate OnRegionInfoChange; public event ChangeDelegate OnEstateInfoChange; public event MessageDelegate OnEstateMessage; private int m_delayCount = 0; #region Region Module interface public string Name { get { return "EstateManagementModule"; } } public Type ReplaceableInterface { get { return null; } } public void Initialise(IConfigSource source) { AllowRegionRestartFromClient = true; IConfig config = source.Configs["EstateManagement"]; if (config != null) AllowRegionRestartFromClient = config.GetBoolean("AllowRegionRestartFromClient", true); } public void AddRegion(Scene scene) { Scene = scene; Scene.RegisterModuleInterface(this); Scene.EventManager.OnNewClient += EventManager_OnNewClient; Scene.EventManager.OnRequestChangeWaterHeight += changeWaterHeight; m_Telehub = new TelehubManager(scene); m_commands = new EstateManagementCommands(this); m_commands.Initialise(); } public void RemoveRegion(Scene scene) {} public void RegionLoaded(Scene scene) { // Sets up the sun module based no the saved Estate and Region Settings // DO NOT REMOVE or the sun will stop working scene.TriggerEstateSunUpdate(); UserManager = scene.RequestModuleInterface(); } public void Close() { m_commands.Close(); } #endregion #region Packet Data Responders private void clientSendDetailedEstateData(IClientAPI remote_client, UUID invoice) { sendDetailedEstateData(remote_client, invoice); sendEstateLists(remote_client, invoice); } private void sendDetailedEstateData(IClientAPI remote_client, UUID invoice) { uint sun = 0; if (Scene.RegionInfo.EstateSettings.FixedSun) sun = (uint)(Scene.RegionInfo.EstateSettings.SunPosition * 1024.0) + 0x1800; UUID estateOwner; estateOwner = Scene.RegionInfo.EstateSettings.EstateOwner; if (Scene.Permissions.IsGod(remote_client.AgentId)) estateOwner = remote_client.AgentId; remote_client.SendDetailedEstateData(invoice, Scene.RegionInfo.EstateSettings.EstateName, Scene.RegionInfo.EstateSettings.EstateID, Scene.RegionInfo.EstateSettings.ParentEstateID, GetEstateFlags(), sun, Scene.RegionInfo.RegionSettings.Covenant, (uint) Scene.RegionInfo.RegionSettings.CovenantChangedDateTime, Scene.RegionInfo.EstateSettings.AbuseEmail, estateOwner); } private void sendEstateLists(IClientAPI remote_client, UUID invoice) { remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.EstateManagers, Scene.RegionInfo.EstateSettings.EstateManagers, Scene.RegionInfo.EstateSettings.EstateID); remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AccessOptions, Scene.RegionInfo.EstateSettings.EstateAccess, Scene.RegionInfo.EstateSettings.EstateID); remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AllowedGroups, Scene.RegionInfo.EstateSettings.EstateGroups, Scene.RegionInfo.EstateSettings.EstateID); remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID); } private void estateSetRegionInfoHandler(bool blockTerraform, bool noFly, bool allowDamage, bool blockLandResell, int maxAgents, float objectBonusFactor, int matureLevel, bool restrictPushObject, bool allowParcelChanges) { if (blockTerraform) Scene.RegionInfo.RegionSettings.BlockTerraform = true; else Scene.RegionInfo.RegionSettings.BlockTerraform = false; if (noFly) Scene.RegionInfo.RegionSettings.BlockFly = true; else Scene.RegionInfo.RegionSettings.BlockFly = false; if (allowDamage) Scene.RegionInfo.RegionSettings.AllowDamage = true; else Scene.RegionInfo.RegionSettings.AllowDamage = false; if (blockLandResell) Scene.RegionInfo.RegionSettings.AllowLandResell = false; else Scene.RegionInfo.RegionSettings.AllowLandResell = true; if((byte)maxAgents <= Scene.RegionInfo.AgentCapacity) Scene.RegionInfo.RegionSettings.AgentLimit = (byte) maxAgents; else Scene.RegionInfo.RegionSettings.AgentLimit = Scene.RegionInfo.AgentCapacity; Scene.RegionInfo.RegionSettings.ObjectBonus = objectBonusFactor; if (matureLevel <= 13) Scene.RegionInfo.RegionSettings.Maturity = 0; else if (matureLevel <= 21) Scene.RegionInfo.RegionSettings.Maturity = 1; else Scene.RegionInfo.RegionSettings.Maturity = 2; if (restrictPushObject) Scene.RegionInfo.RegionSettings.RestrictPushing = true; else Scene.RegionInfo.RegionSettings.RestrictPushing = false; if (allowParcelChanges) Scene.RegionInfo.RegionSettings.AllowLandJoinDivide = true; else Scene.RegionInfo.RegionSettings.AllowLandJoinDivide = false; Scene.RegionInfo.RegionSettings.Save(); TriggerRegionInfoChange(); sendRegionInfoPacketToAll(); } public void setEstateTerrainBaseTexture(int level, UUID texture) { setEstateTerrainBaseTexture(null, level, texture); sendRegionHandshakeToAll(); } public void setEstateTerrainBaseTexture(IClientAPI remoteClient, int level, UUID texture) { if (texture == UUID.Zero) return; switch (level) { case 0: Scene.RegionInfo.RegionSettings.TerrainTexture1 = texture; break; case 1: Scene.RegionInfo.RegionSettings.TerrainTexture2 = texture; break; case 2: Scene.RegionInfo.RegionSettings.TerrainTexture3 = texture; break; case 3: Scene.RegionInfo.RegionSettings.TerrainTexture4 = texture; break; } Scene.RegionInfo.RegionSettings.Save(); TriggerRegionInfoChange(); sendRegionInfoPacketToAll(); } public void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue) { setEstateTerrainTextureHeights(null, corner, lowValue, highValue); } public void setEstateTerrainTextureHeights(IClientAPI client, int corner, float lowValue, float highValue) { switch (corner) { case 0: Scene.RegionInfo.RegionSettings.Elevation1SW = lowValue; Scene.RegionInfo.RegionSettings.Elevation2SW = highValue; break; case 1: Scene.RegionInfo.RegionSettings.Elevation1NW = lowValue; Scene.RegionInfo.RegionSettings.Elevation2NW = highValue; break; case 2: Scene.RegionInfo.RegionSettings.Elevation1SE = lowValue; Scene.RegionInfo.RegionSettings.Elevation2SE = highValue; break; case 3: Scene.RegionInfo.RegionSettings.Elevation1NE = lowValue; Scene.RegionInfo.RegionSettings.Elevation2NE = highValue; break; } Scene.RegionInfo.RegionSettings.Save(); TriggerRegionInfoChange(); sendRegionHandshakeToAll(); sendRegionInfoPacketToAll(); } private void handleCommitEstateTerrainTextureRequest(IClientAPI remoteClient) { // sendRegionHandshakeToAll(); } public void setRegionTerrainSettings(float WaterHeight, float TerrainRaiseLimit, float TerrainLowerLimit, bool UseEstateSun, bool UseFixedSun, float SunHour, bool UseGlobal, bool EstateFixedSun, float EstateSunHour) { // Water Height Scene.RegionInfo.RegionSettings.WaterHeight = WaterHeight; // Terraforming limits Scene.RegionInfo.RegionSettings.TerrainRaiseLimit = TerrainRaiseLimit; Scene.RegionInfo.RegionSettings.TerrainLowerLimit = TerrainLowerLimit; // Time of day / fixed sun Scene.RegionInfo.RegionSettings.UseEstateSun = UseEstateSun; Scene.RegionInfo.RegionSettings.FixedSun = UseFixedSun; Scene.RegionInfo.RegionSettings.SunPosition = SunHour; Scene.TriggerEstateSunUpdate(); //m_log.Debug("[ESTATE]: UFS: " + UseFixedSun.ToString()); //m_log.Debug("[ESTATE]: SunHour: " + SunHour.ToString()); sendRegionInfoPacketToAll(); Scene.RegionInfo.RegionSettings.Save(); TriggerRegionInfoChange(); } private void handleEstateRestartSimRequest(IClientAPI remoteClient, int timeInSeconds) { if (!AllowRegionRestartFromClient) { remoteClient.SendAlertMessage("Region restart has been disabled on this simulator."); return; } IRestartModule restartModule = Scene.RequestModuleInterface(); if (restartModule != null) { List times = new List(); while (timeInSeconds > 0) { times.Add(timeInSeconds); if (timeInSeconds > 300) timeInSeconds -= 120; else if (timeInSeconds > 30) timeInSeconds -= 30; else timeInSeconds -= 15; } restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), false); m_log.InfoFormat( "User {0} requested restart of region {1} in {2} seconds", remoteClient.Name, Scene.Name, times.Count != 0 ? times[0] : 0); } } private void handleChangeEstateCovenantRequest(IClientAPI remoteClient, UUID estateCovenantID) { // m_log.DebugFormat( // "[ESTATE MANAGEMENT MODULE]: Handling request from {0} to change estate covenant to {1}", // remoteClient.Name, estateCovenantID); Scene.RegionInfo.RegionSettings.Covenant = estateCovenantID; Scene.RegionInfo.RegionSettings.CovenantChangedDateTime = Util.UnixTimeSinceEpoch(); Scene.RegionInfo.RegionSettings.Save(); TriggerRegionInfoChange(); } private void handleEstateAccessDeltaRequest(IClientAPI remote_client, UUID invoice, int estateAccessType, UUID user) { // EstateAccessDelta handles Estate Managers, Sim Access, Sim Banlist, allowed Groups.. etc. if (user == Scene.RegionInfo.EstateSettings.EstateOwner) return; // never process EO if ((estateAccessType & 4) != 0) // User add { if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true)) { if ((estateAccessType & 1) != 0) // All estates { List estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); EstateSettings estateSettings; foreach (int estateID in estateIDs) { if (estateID != Scene.RegionInfo.EstateSettings.EstateID) { estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); estateSettings.AddEstateUser(user); estateSettings.Save(); } } } Scene.RegionInfo.EstateSettings.AddEstateUser(user); Scene.RegionInfo.EstateSettings.Save(); TriggerEstateInfoChange(); remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AccessOptions, Scene.RegionInfo.EstateSettings.EstateAccess, Scene.RegionInfo.EstateSettings.EstateID); } else { remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); } } if ((estateAccessType & 8) != 0) // User remove { if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true)) { if ((estateAccessType & 1) != 0) // All estates { List estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); EstateSettings estateSettings; foreach (int estateID in estateIDs) { if (estateID != Scene.RegionInfo.EstateSettings.EstateID) { estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); estateSettings.RemoveEstateUser(user); estateSettings.Save(); } } } Scene.RegionInfo.EstateSettings.RemoveEstateUser(user); Scene.RegionInfo.EstateSettings.Save(); TriggerEstateInfoChange(); remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AccessOptions, Scene.RegionInfo.EstateSettings.EstateAccess, Scene.RegionInfo.EstateSettings.EstateID); } else { remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); } } if ((estateAccessType & 16) != 0) // Group add { if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true)) { if ((estateAccessType & 1) != 0) // All estates { List estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); EstateSettings estateSettings; foreach (int estateID in estateIDs) { if (estateID != Scene.RegionInfo.EstateSettings.EstateID) { estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); estateSettings.AddEstateGroup(user); estateSettings.Save(); } } } Scene.RegionInfo.EstateSettings.AddEstateGroup(user); Scene.RegionInfo.EstateSettings.Save(); TriggerEstateInfoChange(); remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AllowedGroups, Scene.RegionInfo.EstateSettings.EstateGroups, Scene.RegionInfo.EstateSettings.EstateID); } else { remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); } } if ((estateAccessType & 32) != 0) // Group remove { if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true)) { if ((estateAccessType & 1) != 0) // All estates { List estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); EstateSettings estateSettings; foreach (int estateID in estateIDs) { if (estateID != Scene.RegionInfo.EstateSettings.EstateID) { estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); estateSettings.RemoveEstateGroup(user); estateSettings.Save(); } } } Scene.RegionInfo.EstateSettings.RemoveEstateGroup(user); Scene.RegionInfo.EstateSettings.Save(); TriggerEstateInfoChange(); remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AllowedGroups, Scene.RegionInfo.EstateSettings.EstateGroups, Scene.RegionInfo.EstateSettings.EstateID); } else { remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); } } if ((estateAccessType & 64) != 0) // Ban add { if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false)) { EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans; bool alreadyInList = false; for (int i = 0; i < banlistcheck.Length; i++) { if (user == banlistcheck[i].BannedUserID) { alreadyInList = true; break; } } if (!alreadyInList) { if ((estateAccessType & 1) != 0) // All estates { List estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); EstateSettings estateSettings; foreach (int estateID in estateIDs) { if (estateID != Scene.RegionInfo.EstateSettings.EstateID) { EstateBan bitem = new EstateBan(); bitem.BannedUserID = user; bitem.EstateID = (uint)estateID; bitem.BannedHostAddress = "0.0.0.0"; bitem.BannedHostIPMask = "0.0.0.0"; estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); estateSettings.AddBan(bitem); estateSettings.Save(); } } } EstateBan item = new EstateBan(); item.BannedUserID = user; item.EstateID = Scene.RegionInfo.EstateSettings.EstateID; item.BannedHostAddress = "0.0.0.0"; item.BannedHostIPMask = "0.0.0.0"; Scene.RegionInfo.EstateSettings.AddBan(item); Scene.RegionInfo.EstateSettings.Save(); TriggerEstateInfoChange(); ScenePresence s = Scene.GetScenePresence(user); if (s != null) { if (!s.IsChildAgent) { if (!Scene.TeleportClientHome(user, s.ControllingClient)) { s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out."); Scene.CloseAgent(s.UUID, false); } } } } else { remote_client.SendAlertMessage("User is already on the region ban list"); } //Scene.RegionInfo.regionBanlist.Add(Manager(user); remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID); } else { remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); } } if ((estateAccessType & 128) != 0) // Ban remove { if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false)) { EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans; bool alreadyInList = false; EstateBan listitem = null; for (int i = 0; i < banlistcheck.Length; i++) { if (user == banlistcheck[i].BannedUserID) { alreadyInList = true; listitem = banlistcheck[i]; break; } } if (alreadyInList && listitem != null) { if ((estateAccessType & 1) != 0) // All estates { List estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); EstateSettings estateSettings; foreach (int estateID in estateIDs) { if (estateID != Scene.RegionInfo.EstateSettings.EstateID) { estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); estateSettings.RemoveBan(user); estateSettings.Save(); } } } Scene.RegionInfo.EstateSettings.RemoveBan(listitem.BannedUserID); Scene.RegionInfo.EstateSettings.Save(); TriggerEstateInfoChange(); } else { remote_client.SendAlertMessage("User is not on the region ban list"); } //Scene.RegionInfo.regionBanlist.Add(Manager(user); remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID); } else { remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); } } if ((estateAccessType & 256) != 0) // Manager add { if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true)) { if ((estateAccessType & 1) != 0) // All estates { List estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); EstateSettings estateSettings; foreach (int estateID in estateIDs) { if (estateID != Scene.RegionInfo.EstateSettings.EstateID) { estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); estateSettings.AddEstateManager(user); estateSettings.Save(); } } } Scene.RegionInfo.EstateSettings.AddEstateManager(user); Scene.RegionInfo.EstateSettings.Save(); TriggerEstateInfoChange(); remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.EstateManagers, Scene.RegionInfo.EstateSettings.EstateManagers, Scene.RegionInfo.EstateSettings.EstateID); } else { remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); } } if ((estateAccessType & 512) != 0) // Manager remove { if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true)) { if ((estateAccessType & 1) != 0) // All estates { List estateIDs = Scene.EstateDataService.GetEstatesByOwner(Scene.RegionInfo.EstateSettings.EstateOwner); EstateSettings estateSettings; foreach (int estateID in estateIDs) { if (estateID != Scene.RegionInfo.EstateSettings.EstateID) { estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); estateSettings.RemoveEstateManager(user); estateSettings.Save(); } } } Scene.RegionInfo.EstateSettings.RemoveEstateManager(user); Scene.RegionInfo.EstateSettings.Save(); TriggerEstateInfoChange(); remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.EstateManagers, Scene.RegionInfo.EstateSettings.EstateManagers, Scene.RegionInfo.EstateSettings.EstateID); } else { remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); } } } public void HandleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1) { SceneObjectPart part; switch (cmd) { case "info ui": break; case "connect": // Add the Telehub part = Scene.GetSceneObjectPart((uint)param1); if (part == null) return; SceneObjectGroup grp = part.ParentGroup; m_Telehub.Connect(grp); break; case "delete": // Disconnect Telehub m_Telehub.Disconnect(); break; case "spawnpoint add": // Add SpawnPoint to the Telehub part = Scene.GetSceneObjectPart((uint)param1); if (part == null) return; m_Telehub.AddSpawnPoint(part.AbsolutePosition); break; case "spawnpoint remove": // Remove SpawnPoint from Telehub m_Telehub.RemoveSpawnPoint((int)param1); break; default: break; } if (client != null) SendTelehubInfo(client); } private void SendSimulatorBlueBoxMessage( IClientAPI remote_client, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message) { IDialogModule dm = Scene.RequestModuleInterface(); if (dm != null) dm.SendNotificationToUsersInRegion(senderID, senderName, message); } private void SendEstateBlueBoxMessage( IClientAPI remote_client, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message) { TriggerEstateMessage(senderID, senderName, message); } private void handleEstateDebugRegionRequest( IClientAPI remote_client, UUID invoice, UUID senderID, bool disableScripts, bool disableCollisions, bool disablePhysics) { Scene.RegionInfo.RegionSettings.DisablePhysics = disablePhysics; Scene.RegionInfo.RegionSettings.DisableScripts = disableScripts; Scene.RegionInfo.RegionSettings.DisableCollisions = disableCollisions; Scene.RegionInfo.RegionSettings.Save(); TriggerRegionInfoChange(); ISceneCommandsModule scm = Scene.RequestModuleInterface(); if (scm != null) { scm.SetSceneDebugOptions( new Dictionary() { { "scripting", (!disableScripts).ToString() }, { "collisions", (!disableCollisions).ToString() }, { "physics", (!disablePhysics).ToString() } } ); } } private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey) { if (!Scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false)) return; if (prey != UUID.Zero) { ScenePresence s = Scene.GetScenePresence(prey); if (s != null) { if (!Scene.TeleportClientHome(prey, s.ControllingClient)) { s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); Scene.CloseAgent(s.UUID, false); } } } } private void handleEstateTeleportAllUsersHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID) { if (!Scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false)) return; Scene.ForEachRootClient(delegate(IClientAPI client) { if (client.AgentId != senderID) { // make sure they are still there, we could be working down a long list // Also make sure they are actually in the region ScenePresence p; if(Scene.TryGetScenePresence(client.AgentId, out p)) { if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient)) { p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); Scene.CloseAgent(p.UUID, false); } } } }); } private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID) { lock (this) { if ((TerrainUploader != null) && (XferID == TerrainUploader.XferID)) { remoteClient.OnXferReceive -= TerrainUploader.XferReceive; remoteClient.OnAbortXfer -= AbortTerrainXferHandler; TerrainUploader.TerrainUploadDone -= HandleTerrainApplication; TerrainUploader = null; remoteClient.SendAlertMessage("Terrain Upload aborted by the client"); } } } private void HandleTerrainApplication(string filename, byte[] terrainData, IClientAPI remoteClient) { lock (this) { remoteClient.OnXferReceive -= TerrainUploader.XferReceive; remoteClient.OnAbortXfer -= AbortTerrainXferHandler; TerrainUploader.TerrainUploadDone -= HandleTerrainApplication; TerrainUploader = null; } remoteClient.SendAlertMessage("Terrain Upload Complete. Loading...."); ITerrainModule terr = Scene.RequestModuleInterface(); if (terr != null) { m_log.Warn("[CLIENT]: Got Request to Send Terrain in region " + Scene.RegionInfo.RegionName); try { MemoryStream terrainStream = new MemoryStream(terrainData); terr.LoadFromStream(filename, terrainStream); terrainStream.Close(); 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) { m_log.ErrorFormat("[TERRAIN]: Error Saving a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString()); remoteClient.SendAlertMessage("There was an IO Exception loading your terrain. Please check free space."); return; } catch (SecurityException e) { m_log.ErrorFormat("[TERRAIN]: Error Saving a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString()); remoteClient.SendAlertMessage("There was a security Exception loading your terrain. Please check the security on the simulator drive"); return; } catch (UnauthorizedAccessException e) { m_log.ErrorFormat("[TERRAIN]: Error Saving a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString()); remoteClient.SendAlertMessage("There was a security Exception loading your terrain. Please check the security on the simulator drive"); return; } catch (Exception e) { m_log.ErrorFormat("[TERRAIN]: Error loading a terrain file uploaded via the estate tools. It gave us the following error: {0}", e.ToString()); remoteClient.SendAlertMessage("There was a general error loading your terrain. Please fix the terrain file and try again"); } } else { remoteClient.SendAlertMessage("Unable to apply terrain. Cannot get an instance of the terrain module"); } } private void handleUploadTerrain(IClientAPI remote_client, string clientFileName) { lock (this) { if (TerrainUploader == null) { m_log.DebugFormat("Starting to receive uploaded terrain"); TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName); remote_client.OnXferReceive += TerrainUploader.XferReceive; remote_client.OnAbortXfer += AbortTerrainXferHandler; TerrainUploader.TerrainUploadDone += HandleTerrainApplication; TerrainUploader.RequestStartXfer(remote_client); } else { remote_client.SendAlertMessage("Another Terrain Upload is in progress. Please wait your turn!"); } } } public bool IsTerrainXfer(ulong xferID) { lock (this) { if (TerrainUploader == null) return false; else return TerrainUploader.XferID == xferID; } } private void handleTerrainRequest(IClientAPI remote_client, string clientFileName) { // Save terrain here ITerrainModule terr = Scene.RequestModuleInterface(); if (terr != null) { m_log.Warn("[CLIENT]: Got Request to Send Terrain in region " + Scene.RegionInfo.RegionName); if (File.Exists(Util.dataDir() + "/terrain.raw")) { File.Delete(Util.dataDir() + "/terrain.raw"); } terr.SaveToFile(Util.dataDir() + "/terrain.raw"); FileStream input = new FileStream(Util.dataDir() + "/terrain.raw", FileMode.Open); byte[] bdata = new byte[input.Length]; input.Read(bdata, 0, (int)input.Length); remote_client.SendAlertMessage("Terrain file written, starting download..."); Scene.XferManager.AddNewFile("terrain.raw", bdata); // Tell client about it m_log.Warn("[CLIENT]: Sending Terrain to " + remote_client.Name); remote_client.SendInitiateDownload("terrain.raw", clientFileName); } } private void HandleRegionInfoRequest(IClientAPI remote_client) { RegionInfoForEstateMenuArgs args = new RegionInfoForEstateMenuArgs(); args.billableFactor = Scene.RegionInfo.EstateSettings.BillableFactor; args.estateID = Scene.RegionInfo.EstateSettings.EstateID; args.maxAgents = (byte)Scene.RegionInfo.RegionSettings.AgentLimit; args.objectBonusFactor = (float)Scene.RegionInfo.RegionSettings.ObjectBonus; args.parentEstateID = Scene.RegionInfo.EstateSettings.ParentEstateID; args.pricePerMeter = Scene.RegionInfo.EstateSettings.PricePerMeter; args.redirectGridX = Scene.RegionInfo.EstateSettings.RedirectGridX; args.redirectGridY = Scene.RegionInfo.EstateSettings.RedirectGridY; args.regionFlags = GetRegionFlags(); args.simAccess = Scene.RegionInfo.AccessLevel; args.sunHour = (float)Scene.RegionInfo.RegionSettings.SunPosition; args.terrainLowerLimit = (float)Scene.RegionInfo.RegionSettings.TerrainLowerLimit; args.terrainRaiseLimit = (float)Scene.RegionInfo.RegionSettings.TerrainRaiseLimit; args.useEstateSun = Scene.RegionInfo.RegionSettings.UseEstateSun; args.waterHeight = (float)Scene.RegionInfo.RegionSettings.WaterHeight; args.simName = Scene.RegionInfo.RegionName; args.regionType = Scene.RegionInfo.RegionType; remote_client.SendRegionInfoToEstateMenu(args); } private void HandleEstateCovenantRequest(IClientAPI remote_client) { remote_client.SendEstateCovenantInformation(Scene.RegionInfo.RegionSettings.Covenant); } private void HandleLandStatRequest(int parcelID, uint reportType, uint requestFlags, string filter, IClientAPI remoteClient) { if (!Scene.Permissions.CanIssueEstateCommand(remoteClient.AgentId, false)) return; Dictionary sceneData = null; if (reportType == 1) { sceneData = Scene.PhysicsScene.GetTopColliders(); } else if (reportType == 0) { IScriptModule scriptModule = Scene.RequestModuleInterface(); if (scriptModule != null) sceneData = scriptModule.GetObjectScriptsExecutionTimes(); } List SceneReport = new List(); if (sceneData != null) { var sortedSceneData = sceneData.Select( item => new { Measurement = item.Value, Part = Scene.GetSceneObjectPart(item.Key) }); sortedSceneData.OrderBy(item => item.Measurement); int items = 0; foreach (var entry in sortedSceneData) { // The object may have been deleted since we received the data. if (entry.Part == null) continue; // Don't show scripts that haven't executed or where execution time is below one microsecond in // order to produce a more readable report. if (entry.Measurement < 0.001) continue; items++; SceneObjectGroup so = entry.Part.ParentGroup; LandStatReportItem lsri = new LandStatReportItem(); lsri.LocationX = so.AbsolutePosition.X; lsri.LocationY = so.AbsolutePosition.Y; lsri.LocationZ = so.AbsolutePosition.Z; lsri.Score = entry.Measurement; lsri.TaskID = so.UUID; lsri.TaskLocalID = so.LocalId; lsri.TaskName = entry.Part.Name; lsri.OwnerName = UserManager.GetUserName(so.OwnerID); if (filter.Length != 0) { if ((lsri.OwnerName.Contains(filter) || lsri.TaskName.Contains(filter))) { } else { continue; } } SceneReport.Add(lsri); if (items >= 100) break; } } remoteClient.SendLandStatReply(reportType, requestFlags, (uint)SceneReport.Count,SceneReport.ToArray()); } #endregion #region Outgoing Packets public void sendRegionInfoPacketToAll() { Scene.ForEachRootClient(delegate(IClientAPI client) { HandleRegionInfoRequest(client); }); } public void sendRegionHandshake(IClientAPI remoteClient) { RegionHandshakeArgs args = new RegionHandshakeArgs(); args.isEstateManager = Scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(remoteClient.AgentId); if (Scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero && Scene.RegionInfo.EstateSettings.EstateOwner == remoteClient.AgentId) args.isEstateManager = true; args.billableFactor = Scene.RegionInfo.EstateSettings.BillableFactor; args.terrainStartHeight0 = (float)Scene.RegionInfo.RegionSettings.Elevation1SW; args.terrainHeightRange0 = (float)Scene.RegionInfo.RegionSettings.Elevation2SW; args.terrainStartHeight1 = (float)Scene.RegionInfo.RegionSettings.Elevation1NW; args.terrainHeightRange1 = (float)Scene.RegionInfo.RegionSettings.Elevation2NW; args.terrainStartHeight2 = (float)Scene.RegionInfo.RegionSettings.Elevation1SE; args.terrainHeightRange2 = (float)Scene.RegionInfo.RegionSettings.Elevation2SE; args.terrainStartHeight3 = (float)Scene.RegionInfo.RegionSettings.Elevation1NE; args.terrainHeightRange3 = (float)Scene.RegionInfo.RegionSettings.Elevation2NE; args.simAccess = Scene.RegionInfo.AccessLevel; args.waterHeight = (float)Scene.RegionInfo.RegionSettings.WaterHeight; args.regionFlags = GetRegionFlags(); args.regionName = Scene.RegionInfo.RegionName; args.SimOwner = Scene.RegionInfo.EstateSettings.EstateOwner; args.terrainBase0 = UUID.Zero; args.terrainBase1 = UUID.Zero; args.terrainBase2 = UUID.Zero; args.terrainBase3 = UUID.Zero; args.terrainDetail0 = Scene.RegionInfo.RegionSettings.TerrainTexture1; args.terrainDetail1 = Scene.RegionInfo.RegionSettings.TerrainTexture2; args.terrainDetail2 = Scene.RegionInfo.RegionSettings.TerrainTexture3; args.terrainDetail3 = Scene.RegionInfo.RegionSettings.TerrainTexture4; // m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 1 {0} for region {1}", args.terrainDetail0, Scene.RegionInfo.RegionName); // m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 2 {0} for region {1}", args.terrainDetail1, Scene.RegionInfo.RegionName); // m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 3 {0} for region {1}", args.terrainDetail2, Scene.RegionInfo.RegionName); // m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 4 {0} for region {1}", args.terrainDetail3, Scene.RegionInfo.RegionName); remoteClient.SendRegionHandshake(Scene.RegionInfo,args); } public void sendRegionHandshakeToAll() { Scene.ForEachClient(sendRegionHandshake); } public void handleEstateChangeInfo(IClientAPI remoteClient, UUID invoice, UUID senderID, UInt32 parms1, UInt32 parms2) { if (parms2 == 0) { Scene.RegionInfo.EstateSettings.UseGlobalTime = true; Scene.RegionInfo.EstateSettings.SunPosition = 0.0; } else { Scene.RegionInfo.EstateSettings.UseGlobalTime = false; Scene.RegionInfo.EstateSettings.SunPosition = (parms2 - 0x1800)/1024.0; // Warning: FixedSun should be set to True, otherwise this sun position won't be used. } if ((parms1 & 0x00000010) != 0) Scene.RegionInfo.EstateSettings.FixedSun = true; else Scene.RegionInfo.EstateSettings.FixedSun = false; if ((parms1 & 0x00008000) != 0) Scene.RegionInfo.EstateSettings.PublicAccess = true; else Scene.RegionInfo.EstateSettings.PublicAccess = false; if ((parms1 & 0x10000000) != 0) Scene.RegionInfo.EstateSettings.AllowVoice = true; else Scene.RegionInfo.EstateSettings.AllowVoice = false; if ((parms1 & 0x00100000) != 0) Scene.RegionInfo.EstateSettings.AllowDirectTeleport = true; else Scene.RegionInfo.EstateSettings.AllowDirectTeleport = false; if ((parms1 & 0x00800000) != 0) Scene.RegionInfo.EstateSettings.DenyAnonymous = true; else Scene.RegionInfo.EstateSettings.DenyAnonymous = false; if ((parms1 & 0x01000000) != 0) Scene.RegionInfo.EstateSettings.DenyIdentified = true; else Scene.RegionInfo.EstateSettings.DenyIdentified = false; if ((parms1 & 0x02000000) != 0) Scene.RegionInfo.EstateSettings.DenyTransacted = true; else Scene.RegionInfo.EstateSettings.DenyTransacted = false; if ((parms1 & 0x40000000) != 0) Scene.RegionInfo.EstateSettings.DenyMinors = true; else Scene.RegionInfo.EstateSettings.DenyMinors = false; Scene.RegionInfo.EstateSettings.Save(); TriggerEstateInfoChange(); Scene.TriggerEstateSunUpdate(); sendDetailedEstateData(remoteClient, invoice); } #endregion #region Other Functions public void changeWaterHeight(float height) { setRegionTerrainSettings(height, (float)Scene.RegionInfo.RegionSettings.TerrainRaiseLimit, (float)Scene.RegionInfo.RegionSettings.TerrainLowerLimit, Scene.RegionInfo.RegionSettings.UseEstateSun, Scene.RegionInfo.RegionSettings.FixedSun, (float)Scene.RegionInfo.RegionSettings.SunPosition, Scene.RegionInfo.EstateSettings.UseGlobalTime, Scene.RegionInfo.EstateSettings.FixedSun, (float)Scene.RegionInfo.EstateSettings.SunPosition); sendRegionInfoPacketToAll(); } #endregion private void EventManager_OnNewClient(IClientAPI client) { client.OnDetailedEstateDataRequest += clientSendDetailedEstateData; client.OnSetEstateFlagsRequest += estateSetRegionInfoHandler; // client.OnSetEstateTerrainBaseTexture += setEstateTerrainBaseTexture; client.OnSetEstateTerrainDetailTexture += setEstateTerrainBaseTexture; client.OnSetEstateTerrainTextureHeights += setEstateTerrainTextureHeights; client.OnCommitEstateTerrainTextureRequest += handleCommitEstateTerrainTextureRequest; client.OnSetRegionTerrainSettings += setRegionTerrainSettings; client.OnEstateRestartSimRequest += handleEstateRestartSimRequest; client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest; client.OnEstateChangeInfo += handleEstateChangeInfo; client.OnEstateManageTelehub += HandleOnEstateManageTelehub; client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest; client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage; client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage; client.OnEstateDebugRegionRequest += handleEstateDebugRegionRequest; client.OnEstateTeleportOneUserHomeRequest += handleEstateTeleportOneUserHomeRequest; client.OnEstateTeleportAllUsersHomeRequest += handleEstateTeleportAllUsersHomeRequest; client.OnRequestTerrain += handleTerrainRequest; client.OnUploadTerrain += handleUploadTerrain; client.OnRegionInfoRequest += HandleRegionInfoRequest; client.OnEstateCovenantRequest += HandleEstateCovenantRequest; client.OnLandStatRequest += HandleLandStatRequest; sendRegionHandshake(client); } public uint GetRegionFlags() { RegionFlags flags = RegionFlags.None; // Fully implemented // if (Scene.RegionInfo.RegionSettings.AllowDamage) flags |= RegionFlags.AllowDamage; if (Scene.RegionInfo.RegionSettings.BlockTerraform) flags |= RegionFlags.BlockTerraform; if (!Scene.RegionInfo.RegionSettings.AllowLandResell) flags |= RegionFlags.BlockLandResell; if (Scene.RegionInfo.RegionSettings.DisableCollisions) flags |= RegionFlags.SkipCollisions; if (Scene.RegionInfo.RegionSettings.DisableScripts) flags |= RegionFlags.SkipScripts; if (Scene.RegionInfo.RegionSettings.DisablePhysics) flags |= RegionFlags.SkipPhysics; if (Scene.RegionInfo.RegionSettings.BlockFly) flags |= RegionFlags.NoFly; if (Scene.RegionInfo.RegionSettings.RestrictPushing) flags |= RegionFlags.RestrictPushObject; if (Scene.RegionInfo.RegionSettings.AllowLandJoinDivide) flags |= RegionFlags.AllowParcelChanges; if (Scene.RegionInfo.RegionSettings.BlockShowInSearch) flags |= RegionFlags.BlockParcelSearch; if (Scene.RegionInfo.RegionSettings.FixedSun) flags |= RegionFlags.SunFixed; if (Scene.RegionInfo.RegionSettings.Sandbox) flags |= RegionFlags.Sandbox; if (Scene.RegionInfo.EstateSettings.AllowVoice) flags |= RegionFlags.AllowVoice; if (Scene.RegionInfo.EstateSettings.AllowLandmark) flags |= RegionFlags.AllowLandmark; if (Scene.RegionInfo.EstateSettings.AllowSetHome) flags |= RegionFlags.AllowSetHome; if (Scene.RegionInfo.EstateSettings.BlockDwell) flags |= RegionFlags.BlockDwell; if (Scene.RegionInfo.EstateSettings.ResetHomeOnTeleport) flags |= RegionFlags.ResetHomeOnTeleport; // TODO: SkipUpdateInterestList // Omitted // // Omitted: NullLayer (what is that?) // Omitted: SkipAgentAction (what does it do?) return (uint)flags; } public uint GetEstateFlags() { RegionFlags flags = RegionFlags.None; if (Scene.RegionInfo.EstateSettings.FixedSun) flags |= RegionFlags.SunFixed; if (Scene.RegionInfo.EstateSettings.PublicAccess) flags |= (RegionFlags.PublicAllowed | RegionFlags.ExternallyVisible); if (Scene.RegionInfo.EstateSettings.AllowVoice) flags |= RegionFlags.AllowVoice; if (Scene.RegionInfo.EstateSettings.AllowDirectTeleport) flags |= RegionFlags.AllowDirectTeleport; if (Scene.RegionInfo.EstateSettings.DenyAnonymous) flags |= RegionFlags.DenyAnonymous; if (Scene.RegionInfo.EstateSettings.DenyIdentified) flags |= RegionFlags.DenyIdentified; if (Scene.RegionInfo.EstateSettings.DenyTransacted) flags |= RegionFlags.DenyTransacted; if (Scene.RegionInfo.EstateSettings.AbuseEmailToEstateOwner) flags |= RegionFlags.AbuseEmailToEstateOwner; if (Scene.RegionInfo.EstateSettings.BlockDwell) flags |= RegionFlags.BlockDwell; if (Scene.RegionInfo.EstateSettings.EstateSkipScripts) flags |= RegionFlags.EstateSkipScripts; if (Scene.RegionInfo.EstateSettings.ResetHomeOnTeleport) flags |= RegionFlags.ResetHomeOnTeleport; if (Scene.RegionInfo.EstateSettings.TaxFree) flags |= RegionFlags.TaxFree; if (Scene.RegionInfo.EstateSettings.AllowLandmark) flags |= RegionFlags.AllowLandmark; if (Scene.RegionInfo.EstateSettings.AllowParcelChanges) flags |= RegionFlags.AllowParcelChanges; if (Scene.RegionInfo.EstateSettings.AllowSetHome) flags |= RegionFlags.AllowSetHome; if (Scene.RegionInfo.EstateSettings.DenyMinors) flags |= (RegionFlags)(1 << 30); return (uint)flags; } public bool IsManager(UUID avatarID) { if (avatarID == Scene.RegionInfo.EstateSettings.EstateOwner) return true; List ems = new List(Scene.RegionInfo.EstateSettings.EstateManagers); if (ems.Contains(avatarID)) return true; return false; } public void TriggerRegionInfoChange() { m_regionChangeTimer.Stop(); m_regionChangeTimer.Start(); ChangeDelegate change = OnRegionInfoChange; if (change != null) change(Scene.RegionInfo.RegionID); } public void TriggerEstateInfoChange() { ChangeDelegate change = OnEstateInfoChange; if (change != null) change(Scene.RegionInfo.RegionID); } public void TriggerEstateMessage(UUID fromID, string fromName, string message) { MessageDelegate onmessage = OnEstateMessage; if (onmessage != null) onmessage(Scene.RegionInfo.RegionID, fromID, fromName, message); } private void SendTelehubInfo(IClientAPI client) { RegionSettings settings = this.Scene.RegionInfo.RegionSettings; SceneObjectGroup telehub = null; if (settings.TelehubObject != UUID.Zero && (telehub = Scene.GetSceneObjectGroup(settings.TelehubObject)) != null) { List spawnPoints = new List(); foreach (SpawnPoint sp in settings.SpawnPoints()) { spawnPoints.Add(sp.GetLocation(Vector3.Zero, Quaternion.Identity)); } client.SendTelehubInfo(settings.TelehubObject, telehub.Name, telehub.AbsolutePosition, telehub.GroupRotation, spawnPoints); } else { client.SendTelehubInfo(UUID.Zero, String.Empty, Vector3.Zero, Quaternion.Identity, new List()); } } } }