/* * 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.Concurrent; 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 OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; using RegionFlags = OpenMetaverse.RegionFlags; using Timer = System.Timers.Timer; 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 bool m_ignoreEstateMinorAccessControl; private bool m_ignoreEstatePaymentAccessControl; private EstateTerrainXferHandler TerrainUploader; public TelehubManager m_Telehub; public event ChangeDelegate OnRegionInfoChange; public event ChangeDelegate OnEstateInfoChange; public event MessageDelegate OnEstateMessage; public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest; public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest; 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); m_ignoreEstateMinorAccessControl = config.GetBoolean("IgnoreEstateMinorAccessControl", true); m_ignoreEstatePaymentAccessControl = config.GetBoolean("IgnoreEstatePaymentAccessControl", 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(); m_regionChangeTimer.Interval = 10000; m_regionChangeTimer.Elapsed += RaiseRegionInfoChange; m_regionChangeTimer.AutoReset = false; } public void RemoveRegion(Scene scene) {} public void RegionLoaded(Scene scene) { UserManager = scene.RequestModuleInterface(); scene.RegionInfo.EstateSettings.DoDenyMinors = !m_ignoreEstateMinorAccessControl; scene.RegionInfo.EstateSettings.DoDenyAnonymous = !m_ignoreEstatePaymentAccessControl; } public void Close() { m_commands.Close(); } #endregion #region IEstateModule Functions 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.GodBlockSearch) flags |= (RegionFlags)(1 << 11); if (Scene.RegionInfo.RegionSettings.Casino) flags |= (RegionFlags)(1 << 10); // 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; if (Scene.RegionInfo.EstateSettings.AllowEnvironmentOverride) flags |= RegionFlags.AllowEnvironmentOverride; // TODO: SkipUpdateInterestList // Omitted // // Omitted: SkipAgentAction (what does it do?) 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 sendRegionHandshakeToAll() { Scene.ForEachClient(SendRegionHandshake); } public void TriggerEstateInfoChange() { OnEstateInfoChange?.Invoke(Scene.RegionInfo.RegionID); } protected void RaiseRegionInfoChange(object sender, ElapsedEventArgs e) { OnRegionInfoChange?.Invoke(Scene.RegionInfo.RegionID); } public void TriggerRegionInfoChange() { m_regionChangeTimer.Stop(); m_regionChangeTimer.Start(); OnRegionInfoChange?.Invoke(Scene.RegionInfo.RegionID); } public void setEstateTerrainBaseTexture(int level, UUID texture) { SetEstateTerrainBaseTexture(null, level, texture); } public void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue) { SetEstateTerrainTextureHeights(null, corner, lowValue, highValue); } public bool IsTerrainXfer(ulong xferID) { lock (this) { if (TerrainUploader == null) return false; else return TerrainUploader.XferID == xferID; } } public string SetEstateOwner(int estateID, UserAccount account) { string response; // get the current settings from DB EstateSettings dbSettings = Scene.EstateDataService.LoadEstateSettings(estateID); if (dbSettings.EstateID == 0) { response = String.Format("No estate found with ID {0}", estateID); } else if (account.PrincipalID == dbSettings.EstateOwner) { response = String.Format("Estate already belongs to {0} ({1} {2})", account.PrincipalID, account.FirstName, account.LastName); } else { dbSettings.EstateOwner = account.PrincipalID; Scene.EstateDataService.StoreEstateSettings(dbSettings); response = String.Empty; // make sure there's a log entry to document the change m_log.InfoFormat("[ESTATE]: Estate Owner for {0} changed to {1} ({2} {3})", dbSettings.EstateName, account.PrincipalID, account.FirstName, account.LastName); // propagate the change List regions = Scene.GetEstateRegions(estateID); UUID regionId = (regions.Count() > 0) ? regions.ElementAt(0) : UUID.Zero; if (!regionId.IsZero()) { OnEstateInfoChange?.Invoke(regionId); } } return response; } public string SetEstateName(int estateID, string newName) { string response; // get the current settings from DB EstateSettings dbSettings = Scene.EstateDataService.LoadEstateSettings(estateID); if (dbSettings.EstateID == 0) { response = String.Format("No estate found with ID {0}", estateID); } else if (newName == dbSettings.EstateName) { response = String.Format("Estate {0} is already named \"{1}\"", estateID, newName); } else { List estates = Scene.EstateDataService.GetEstates(newName); if (estates.Count() > 0) { response = String.Format("An estate named \"{0}\" already exists.", newName); } else { string oldName = dbSettings.EstateName; dbSettings.EstateName = newName; Scene.EstateDataService.StoreEstateSettings(dbSettings); response = String.Empty; // make sure there's a log entry to document the change m_log.InfoFormat("[ESTATE]: Estate {0} renamed from \"{1}\" to \"{2}\"", estateID, oldName, newName); // propagate the change List regions = Scene.GetEstateRegions(estateID); UUID regionId = (regions.Count() > 0) ? regions.ElementAt(0) : UUID.Zero; if (!regionId.IsZero()) { OnEstateInfoChange?.Invoke(regionId); } } } return response; } public string SetRegionEstate(RegionInfo regionInfo, int estateID) { string response; if (regionInfo.EstateSettings.EstateID == estateID) { response = String.Format("\"{0}\" is already part of estate {1}", regionInfo.RegionName, estateID); } else { // get the current settings from DB EstateSettings dbSettings = Scene.EstateDataService.LoadEstateSettings(estateID); if (dbSettings.EstateID == 0) { response = String.Format("No estate found with ID {0}", estateID); } else if (Scene.EstateDataService.LinkRegion(regionInfo.RegionID, estateID)) { // make sure there's a log entry to document the change m_log.InfoFormat("[ESTATE]: Region {0} ({1}) moved to Estate {2} ({3}).", regionInfo.RegionID, regionInfo.RegionName, estateID, dbSettings.EstateName); // propagate the change OnEstateInfoChange?.Invoke(regionInfo.RegionID); response = String.Empty; } else { response = String.Format("Could not move \"{0}\" to estate {1}", regionInfo.RegionName, estateID); } } return response; } public string CreateEstate(string estateName, UUID ownerID) { string response; if (string.IsNullOrEmpty(estateName)) { response = "No estate name specified."; } else { List estates = Scene.EstateDataService.GetEstates(estateName); if (estates.Count() > 0) { response = String.Format("An estate named \"{0}\" already exists.", estateName); } else { EstateSettings settings = Scene.EstateDataService.CreateNewEstate(); if (settings == null) response = String.Format("Unable to create estate \"{0}\" at this simulator", estateName); else { settings.EstateOwner = ownerID; settings.EstateName = estateName; Scene.EstateDataService.StoreEstateSettings(settings); response = String.Empty; } } } return response; } #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) { UUID estateOwner; estateOwner = Scene.RegionInfo.EstateSettings.EstateOwner; remote_client.SendDetailedEstateData(invoice, Scene.RegionInfo.EstateSettings.EstateName, Scene.RegionInfo.EstateSettings.EstateID, Scene.RegionInfo.EstateSettings.ParentEstateID, GetEstateFlags(), 0, 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.AllowedAccess, 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) { Scene.RegionInfo.RegionSettings.BlockTerraform = blockTerraform; Scene.RegionInfo.RegionSettings.BlockFly = noFly; Scene.RegionInfo.RegionSettings.AllowDamage = allowDamage; Scene.RegionInfo.RegionSettings.AllowLandResell = !blockLandResell; Scene.RegionInfo.RegionSettings.RestrictPushing = restrictPushObject; Scene.RegionInfo.RegionSettings.AllowLandJoinDivide = allowParcelChanges; if (maxAgents > 1 && maxAgents <= Scene.RegionInfo.AgentCapacity) Scene.RegionInfo.RegionSettings.AgentLimit = 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; Scene.RegionInfo.RegionSettings.Save(); TriggerRegionInfoChange(); SendRegionInfoPacketToAll(); } public bool SetRegionInfobyCap(OSDMap map) { if(Scene.RegionInfo == null || Scene.RegionInfo.RegionSettings == null) return false; RegionSettings es = Scene.RegionInfo.RegionSettings; OSD tmp; //if (map.TryGetValue("", out tmp) && tmp) if (map.TryGetValue("block_terraform", out tmp) && tmp is not null ) es.BlockTerraform = tmp.AsBoolean(); if (map.TryGetValue("block_fly", out tmp) && tmp is not null) es.BlockFly = tmp.AsBoolean(); //if (map.TryGetValue("block_fly_over", out tmp) && tmp) // es.??? = tmp.AsBoolean()); if (map.TryGetValue("allow_damage", out tmp) && tmp is not null) es.AllowDamage = tmp.AsBoolean(); if (map.TryGetValue("allow_land_resell", out tmp) && tmp is not null) es.AllowLandResell = tmp.AsBoolean(); if (map.TryGetValue("agent_limit", out tmp) && tmp is not null) { int maxagents = tmp.AsInteger(); if (maxagents > 1 && maxagents <= Scene.RegionInfo.AgentCapacity) Scene.RegionInfo.RegionSettings.AgentLimit = maxagents; else Scene.RegionInfo.RegionSettings.AgentLimit = Scene.RegionInfo.AgentCapacity; } if (map.TryGetValue("prim_bonus", out tmp) && tmp is not null) es.ObjectBonus = tmp.AsInteger(); if (map.TryGetValue("sim_access", out tmp) && tmp is not null) { int matureLevel = tmp.AsInteger(); if (matureLevel <= 13) es.Maturity = 0; else if (matureLevel <= 21) es.Maturity = 1; else es.Maturity = 2; } if (map.TryGetValue("restrict_pushobject", out tmp) && tmp is not null) es.RestrictPushing = tmp.AsBoolean(); if (map.TryGetValue("allow_parcel_changes", out tmp) && tmp is not null) es.AllowLandJoinDivide = tmp.AsBoolean(); if (map.TryGetValue("block_parcel_search", out tmp) && tmp is not null) es.BlockShowInSearch = tmp.AsBoolean(); Scene.RegionInfo.RegionSettings.Save(); TriggerRegionInfoChange(); SendRegionInfoPacketToAll(); return true; } public void SetEstateTerrainBaseTexture(IClientAPI remoteClient, int level, UUID texture) { if (texture.IsZero()) return; if(remoteClient is not null && (remoteClient.ViewerFlags & ViewerFlags.TPBR) != 0) { switch (level) { case 0: Scene.RegionInfo.RegionSettings.TerrainPBR1 = texture; break; case 1: Scene.RegionInfo.RegionSettings.TerrainPBR2 = texture; break; case 2: Scene.RegionInfo.RegionSettings.TerrainPBR3 = texture; break; case 3: Scene.RegionInfo.RegionSettings.TerrainPBR4 = texture; break; default: return; } } else { 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; default: return; } } Scene.RegionInfo.RegionSettings.Save(); TriggerRegionInfoChange(); sendRegionHandshakeToAll(); } 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; default: return; } Scene.RegionInfo.RegionSettings.Save(); TriggerRegionInfoChange(); sendRegionHandshakeToAll(); } 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) { double lastwaterlevel = Scene.RegionInfo.RegionSettings.WaterHeight; // 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; if (Scene.PhysicsEnabled && Scene.PhysicsScene != null && lastwaterlevel != WaterHeight) Scene.PhysicsScene.SetWaterLevel(WaterHeight); //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) { if (timeInSeconds == -1) { m_delayCount++; if (m_delayCount > 3) return; restartModule.DelayRestart(3600, "Restart delayed by region manager"); return; } 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 readonly object deltareqLock = new object(); private bool runnigDeltaExec = false; private class EstateAccessDeltaRequest { public IClientAPI remote_client; public UUID invoice; public int estateAccessType; public UUID user; } private BlockingCollection deltaRequests = new BlockingCollection(); 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 EstateAccessDeltaRequest newreq = new EstateAccessDeltaRequest() { remote_client = _remote_client, invoice = _invoice, estateAccessType = _estateAccessType, user = _user }; deltaRequests.Add(newreq); lock(deltareqLock) { if(!runnigDeltaExec) { runnigDeltaExec = true; WorkManager.RunInThreadPool(ExecDeltaRequests,null,"execDeltaRequests"); } } } private void ExecDeltaRequests(object o) { IClientAPI remote_client; UUID invoice; int estateAccessType; UUID user; Dictionary changed = new Dictionary(); Dictionary sendAllowedOrBanList = new Dictionary(); Dictionary sendManagers = new Dictionary(); Dictionary sendGroups = new Dictionary(); List otherEstates = new List(); bool sentAllowedFull = false; bool sentBansFull = false; bool sentGroupsFull = false; bool sentManagersFull = false; EstateAccessDeltaRequest req; while(Scene.IsRunning) { req = null; deltaRequests.TryTake(out req, 500); if(!Scene.IsRunning) break; if(req == null) { if(changed.Count > 0) { foreach(EstateSettings est in changed.Values) Scene.EstateDataService.StoreEstateSettings(est); TriggerEstateInfoChange(); } EstateSettings es = Scene.RegionInfo.EstateSettings; foreach(KeyValuePair kvp in sendAllowedOrBanList) { IClientAPI cli = kvp.Key; UUID invoive = kvp.Value; cli.SendEstateList(invoive, (int)Constants.EstateAccessCodex.AllowedAccess, es.EstateAccess, es.EstateID); cli.SendBannedUserList(invoive, es.EstateBans, es.EstateID); } sendAllowedOrBanList.Clear(); foreach(KeyValuePair kvp in sendManagers) { IClientAPI cli = kvp.Key; cli.SendEstateList(kvp.Value, (int)Constants.EstateAccessCodex.EstateManagers, es.EstateManagers, es.EstateID); } foreach(KeyValuePair kvp in sendGroups) { IClientAPI cli = kvp.Key; cli.SendEstateList(kvp.Value, (int)Constants.EstateAccessCodex.AllowedGroups, es.EstateGroups, es.EstateID); } otherEstates.Clear(); sendAllowedOrBanList.Clear(); sendManagers.Clear(); sendGroups.Clear(); changed.Clear(); lock(deltareqLock) { if(deltaRequests.Count != 0) continue; runnigDeltaExec = false; return; } } remote_client = req.remote_client; if(!remote_client.IsActive) continue; invoice = req.invoice; user = req.user; estateAccessType = req.estateAccessType; bool needReply = ((estateAccessType & 1024) == 0); bool doOtherEstates = ((estateAccessType & 3) != 0); EstateSettings thisSettings = Scene.RegionInfo.EstateSettings; int thisEstateID =(int)thisSettings.EstateID; UUID agentID = remote_client.AgentId; bool isadmin = Scene.Permissions.IsAdministrator(agentID); // just i case recheck rights if (!isadmin && !Scene.Permissions.IsEstateManager(agentID)) { remote_client.SendAlertMessage("Method EstateAccess Failed, you don't have permissions"); continue; } otherEstates.Clear(); if(doOtherEstates) { UUID thisOwner = Scene.RegionInfo.EstateSettings.EstateOwner; List estateIDs = Scene.EstateDataService.GetEstatesByOwner(thisOwner); foreach (int estateID in estateIDs) { if (estateID == thisEstateID) continue; EstateSettings estateSettings; if(changed.ContainsKey(estateID)) estateSettings = changed[estateID]; else estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID); if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID)) continue; otherEstates.Add(estateSettings); } estateIDs.Clear(); } // the commands // first the ones allowed for estate managers on this region if ((estateAccessType & 4) != 0) // User add { if(thisSettings.EstateUsersCount() >= (int)Constants.EstateAccessLimits.AllowedAccess) { if(!sentAllowedFull) { sentAllowedFull = true; remote_client.SendAlertMessage("Estate Allowed users list is full"); } } else { if (doOtherEstates) { foreach (EstateSettings estateSettings in otherEstates) { if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID)) continue; if(estateSettings.EstateUsersCount() >= (int)Constants.EstateAccessLimits.AllowedAccess) continue; estateSettings.AddEstateUser(user); estateSettings.RemoveBan(user); changed[(int)estateSettings.EstateID] = estateSettings; } } thisSettings.AddEstateUser(user); thisSettings.RemoveBan(user); changed[thisEstateID] = thisSettings; if(needReply) sendAllowedOrBanList[remote_client] = invoice; } } if ((estateAccessType & 8) != 0) // User remove { if (doOtherEstates) // All estates { foreach (EstateSettings estateSettings in otherEstates) { if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID)) continue; estateSettings.RemoveEstateUser(user); changed[(int)estateSettings.EstateID] = estateSettings; } } thisSettings.RemoveEstateUser(user); changed[thisEstateID] = thisSettings; if(needReply) sendAllowedOrBanList[remote_client] = invoice; } if ((estateAccessType & 16) != 0) // Group add { if(thisSettings.EstateGroupsCount() >= (int)Constants.EstateAccessLimits.AllowedGroups) { if(!sentGroupsFull) { sentGroupsFull = true; remote_client.SendAlertMessage("Estate Allowed groups list is full"); } } else { if (doOtherEstates) // All estates { foreach (EstateSettings estateSettings in otherEstates) { if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID)) continue; if(estateSettings.EstateGroupsCount() >= (int)Constants.EstateAccessLimits.AllowedGroups) continue; estateSettings.AddEstateGroup(user); changed[(int)estateSettings.EstateID] = estateSettings; } } thisSettings.AddEstateGroup(user); changed[thisEstateID] = thisSettings; sendGroups[remote_client] = invoice; } } if ((estateAccessType & 32) != 0) // Group remove { if (doOtherEstates) // All estates { foreach (EstateSettings estateSettings in otherEstates) { if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID)) continue; estateSettings.RemoveEstateGroup(user); changed[(int)estateSettings.EstateID] = estateSettings; } } thisSettings.RemoveEstateGroup(user); changed[thisEstateID] = thisSettings; sendGroups[remote_client] = invoice; } if ((estateAccessType & 64) != 0) // Ban add { if(thisSettings.EstateBansCount() >= (int)Constants.EstateAccessLimits.EstateBans) { if(!sentBansFull) { sentBansFull = true; remote_client.SendAlertMessage("Estate Ban list is full"); } } else { 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 (doOtherEstates) // All estates { foreach (EstateSettings estateSettings in otherEstates) { if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID)) continue; if(estateSettings.EstateBansCount() >= (int)Constants.EstateAccessLimits.EstateBans) continue; EstateBan bitem = new EstateBan() { BannedUserID = user, EstateID = estateSettings.EstateID, BannedHostAddress = "0.0.0.0", BannedHostIPMask = "0.0.0.0", BanningUserID = remote_client.AgentId, BanTime = Util.UnixTimeSinceEpoch() }; estateSettings.AddBan(bitem); estateSettings.RemoveEstateUser(user); changed[(int)estateSettings.EstateID] = estateSettings; } } EstateBan item = new EstateBan() { BannedUserID = user, EstateID = Scene.RegionInfo.EstateSettings.EstateID, BannedHostAddress = "0.0.0.0", BannedHostIPMask = "0.0.0.0", BanningUserID = remote_client.AgentId, BanTime = Util.UnixTimeSinceEpoch() }; thisSettings.AddBan(item); thisSettings.RemoveEstateUser(user); changed[thisEstateID] = thisSettings; 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); if(needReply) sendAllowedOrBanList[remote_client] = invoice; } } if ((estateAccessType & 128) != 0) // Ban remove { 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 (doOtherEstates) // All estates { foreach (EstateSettings estateSettings in otherEstates) { if(!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID)) continue; estateSettings.RemoveBan(user); changed[(int)estateSettings.EstateID] = estateSettings; } } thisSettings.RemoveBan(listitem.BannedUserID); changed[thisEstateID] = thisSettings; } else { remote_client.SendAlertMessage("User is not on the region ban list"); } if(needReply) sendAllowedOrBanList[remote_client] = invoice; } // last the ones only for owners of this region if (!Scene.Permissions.CanIssueEstateCommand(agentID, true)) { remote_client.SendAlertMessage("Method EstateAccess Failed, you don't have permissions"); continue; } if ((estateAccessType & 256) != 0) // Manager add { if(thisSettings.EstateManagersCount() >= (int)Constants.EstateAccessLimits.EstateManagers) { if(!sentManagersFull) { sentManagersFull = true; remote_client.SendAlertMessage("Estate Managers list is full"); } } else { if (doOtherEstates) // All estates { foreach (EstateSettings estateSettings in otherEstates) { if(!isadmin && !estateSettings.IsEstateOwner(agentID)) // redundante check? continue; if(estateSettings.EstateManagersCount() >= (int)Constants.EstateAccessLimits.EstateManagers) continue; estateSettings.AddEstateManager(user); changed[(int)estateSettings.EstateID] = estateSettings; } } thisSettings.AddEstateManager(user); changed[thisEstateID] = thisSettings; sendManagers[remote_client] = invoice; } } if ((estateAccessType & 512) != 0) // Manager remove { if (doOtherEstates) // All estates { foreach (EstateSettings estateSettings in otherEstates) { if(!isadmin && !estateSettings.IsEstateOwner(agentID)) continue; estateSettings.RemoveEstateManager(user); changed[(int)estateSettings.EstateID] = estateSettings; } } thisSettings.RemoveEstateManager(user); changed[thisEstateID] = thisSettings; sendManagers[remote_client] = invoice; } } lock(deltareqLock) runnigDeltaExec = false; } 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, bool kick) { if (prey.IsZero()) return; EstateTeleportOneUserHomeRequest evOverride = OnEstateTeleportOneUserHomeRequest; if(evOverride != null) { evOverride(remover_client, invoice, senderID, prey, kick); return; } if (!Scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false)) return; ScenePresence s = Scene.GetScenePresence(prey); if (s != null && !s.IsDeleted && !s.IsInTransit) { if (kick) { s.ControllingClient.Kick("You have been kicked"); Scene.CloseAgent(s.UUID, false); } else if (!Scene.TeleportClientHome(prey, s.ControllingClient)) { s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed "); Scene.CloseAgent(s.UUID, false); } } } private void HandleEstateTeleportAllUsersHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID) { EstateTeleportAllUsersHomeRequest evOverride = OnEstateTeleportAllUsersHomeRequest; if(evOverride != null) { evOverride(remover_client, invoice, senderID); return; } 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 if(Scene.TryGetScenePresence(client.AgentId, out ScenePresence 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; } m_log.DebugFormat("[CLIENT]: Terrain upload from {0} to {1} complete.", remoteClient.Name, Scene.Name); remoteClient.SendAlertMessage("Terrain Upload Complete. Loading...."); ITerrainModule terr = Scene.RequestModuleInterface(); if (terr != null) { try { using (MemoryStream terrainStream = new MemoryStream(terrainData)) terr.LoadFromStream(filename, terrainStream); 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( "[TERRAIN]: Started receiving terrain upload for region {0} from {1}", Scene.Name, remote_client.Name); 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!"); } } } 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"); byte[] bdata; using(FileStream input = new FileStream(Util.dataDir() + "/terrain.raw",FileMode.Open)) { bdata = new byte[input.Length]; input.Read(bdata, 0, (int)input.Length); } if(bdata == null || bdata.Length == 0) { remote_client.SendAlertMessage("Terrain error"); return; } remote_client.SendAlertMessage("Terrain file written, starting download..."); string xfername = (UUID.Random()).ToString(); Scene.XferManager.AddNewFile(xfername, bdata); m_log.DebugFormat("[CLIENT]: Sending terrain for region {0} to {1}", Scene.Name, remote_client.Name); remote_client.SendInitiateDownload(xfername, clientFileName); } } public void HandleRegionInfoRequest(IClientAPI remote_client) { RegionInfoForEstateMenuArgs args = new RegionInfoForEstateMenuArgs() { billableFactor = Scene.RegionInfo.EstateSettings.BillableFactor, estateID = Scene.RegionInfo.EstateSettings.EstateID, maxAgents = Scene.RegionInfo.RegionSettings.AgentLimit, objectBonusFactor = (float)Scene.RegionInfo.RegionSettings.ObjectBonus, parentEstateID = Scene.RegionInfo.EstateSettings.ParentEstateID, pricePerMeter = Scene.RegionInfo.EstateSettings.PricePerMeter, redirectGridX = Scene.RegionInfo.EstateSettings.RedirectGridX, redirectGridY = Scene.RegionInfo.EstateSettings.RedirectGridY, regionFlags = GetRegionFlags(), simAccess = Scene.RegionInfo.AccessLevel, sunHour = 0, terrainLowerLimit = (float)Scene.RegionInfo.RegionSettings.TerrainLowerLimit, terrainRaiseLimit = (float)Scene.RegionInfo.RegionSettings.TerrainRaiseLimit, useEstateSun = false, waterHeight = (float)Scene.RegionInfo.RegionSettings.WaterHeight, simName = Scene.RegionInfo.RegionName, regionType = Scene.RegionInfo.RegionType, AgentCapacity = Scene.RegionInfo.AgentCapacity, ObjectsCapacity = Scene.RegionInfo.ObjectCapacity, }; 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 (reportType == 1) { LandCollidersStatRequest(parcelID, requestFlags, filter, remoteClient); return; } if (reportType != 0) remoteClient.SendLandStatReply(reportType, requestFlags, 0, new LandStatReportItem[0]); IScriptModule scriptModule = Scene.RequestModuleInterface(); if (scriptModule == null) remoteClient.SendLandStatReply(reportType, requestFlags, 0, new LandStatReportItem[0]); ICollection sceneData = scriptModule.GetTopObjectStats( 0.001f, 1024, out float totaltime, out float totalmemory); if(sceneData == null || sceneData.Count == 0) remoteClient.SendLandStatReply(0, requestFlags, 0, new LandStatReportItem[0]); IUrlModule urlModule = Scene.RequestModuleInterface(); //reformat the name so we don't have to do it on every item bool hasfilter = false; if ((requestFlags & 0x0e) != 0 && !string.IsNullOrWhiteSpace(filter)) { if ((requestFlags & 0x00000002) != 0) { int indx = filter.IndexOf('.'); if(indx > 0) { string tmp = filter.Substring(0, indx); if(indx < filter.Length - 1) { tmp += " " + filter.Substring(indx +1); } filter = tmp; } } filter.Trim(); filter = filter.ToLower(); hasfilter = filter.Length > 0; } var sortedSceneData = sceneData.OrderByDescending(e => e.time); int items = 0; List SceneReport = new List(); foreach (var entry in sortedSceneData) { // The object may have been deleted since we received the data. SceneObjectPart sop = Scene.GetSceneObjectPart(entry.localID); if(sop == null) continue; SceneObjectGroup so = sop.ParentGroup; if (so == null || so.IsDeleted || so.inTransit) continue; int urls_used = 0; if (urlModule != null) { urls_used = urlModule.GetUrlCount(sop.UUID); // Don't show scripts that haven't executed or where execution time is below one microsecond in // order to produce a more readable report. // Unless they are using URLs or using 1024 bytes or more. if (entry.time < 0.001 && entry.memory < 1024 && urls_used == 0) continue; } else if (entry.time < 0.001 && entry.memory < 1024) continue; ILandObject land = Scene.LandChannel.GetLandObject(so.AbsolutePosition); if((requestFlags & 1) != 0 && land.LandData.LocalID != parcelID) continue; string owner_name = UserManager.GetUserName(so.OwnerID); string task_name = so.Name; string parcel_name = land != null ? land.LandData.Name : "unknown"; if (hasfilter) { if ((requestFlags & 0x00000002) != 0) { if (!owner_name.ToLower().Contains(filter)) continue; } else if ((requestFlags & 0x00000004) != 0) { if (!task_name.ToLower().Contains(filter)) continue; } else if ((requestFlags & 0x00000008) != 0) { if (!parcel_name.ToLower().Contains(filter)) continue; } } LandStatReportItem lsri = new LandStatReportItem() { LocationX = so.AbsolutePosition.X, LocationY = so.AbsolutePosition.Y, LocationZ = so.AbsolutePosition.Z, Score = entry.time, TaskID = so.UUID, TaskLocalID = so.LocalId, TaskName = task_name, OwnerName = owner_name, OwnerID = so.OwnerID, Bytes = entry.memory, Urls = urls_used, Time = Utils.DateTimeToUnixTime(sop.Rezzed), Parcel = parcel_name }; items++; SceneReport.Add(lsri); if (items >= 100) break; } remoteClient.SendLandStatReply(0, requestFlags, (uint)SceneReport.Count,SceneReport.ToArray()); } private void LandCollidersStatRequest(int parcelID, uint requestFlags, string filter, IClientAPI remoteClient) { if (!Scene.Permissions.CanIssueEstateCommand(remoteClient.AgentId, false)) remoteClient.SendLandStatReply(1, requestFlags, 0, new LandStatReportItem[0]); Dictionary sceneData = Scene.PhysicsScene.GetTopColliders(); List SceneReport = new List(); if (sceneData != null) { //reformat the name so we don't have to do it on every item bool hasfilter = false; if ((requestFlags & 0x0c) != 0 && !string.IsNullOrWhiteSpace(filter)) { if ((requestFlags & 0x00000002) != 0) { int indx = filter.IndexOf('.'); if (indx > 0) { string tmp = filter.Substring(0, indx); if (indx < filter.Length - 1) { tmp += " " + filter.Substring(indx + 1); } filter = tmp; } } filter.Trim(); filter = filter.ToLower(); hasfilter = filter.Length > 0; } int items = 0; foreach (KeyValuePair kvp in sceneData) { if (kvp.Value < 0.001) continue; // The object may have been deleted since we received the data. SceneObjectPart sop = Scene.GetSceneObjectPart(kvp.Key); if(sop == null) continue; SceneObjectGroup so = sop.ParentGroup; if (so == null || so.IsDeleted || so.inTransit) 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. // Unless they are using URLs or using 1024 bytes or more. ILandObject land = Scene.LandChannel.GetLandObject(so.AbsolutePosition); if ((requestFlags & 1) != 0 && land.LandData.LocalID != parcelID) continue; string owner_name = UserManager.GetUserName(so.OwnerID); string task_name = so.Name; string parcel_name = land != null ? land.LandData.Name : "unknown"; if (hasfilter) { if ((requestFlags & 0x00000002) != 0) { if (!owner_name.ToLower().Contains(filter)) continue; } else if ((requestFlags & 0x00000004) != 0) { if (!task_name.ToLower().Contains(filter)) continue; } else if ((requestFlags & 0x00000008) != 0) { if (!parcel_name.ToLower().Contains(filter)) continue; } } LandStatReportItem lsri = new LandStatReportItem() { LocationX = so.AbsolutePosition.X, LocationY = so.AbsolutePosition.Y, LocationZ = so.AbsolutePosition.Z, Score = kvp.Value, TaskID = so.UUID, TaskLocalID = so.LocalId, TaskName = task_name, OwnerName = owner_name, OwnerID = so.OwnerID, Time = Utils.DateTimeToUnixTime(sop.Rezzed), Parcel = parcel_name }; items++; SceneReport.Add(lsri); if (items >= 100) break; } } remoteClient.SendLandStatReply(1, requestFlags, (uint)SceneReport.Count, SceneReport.ToArray()); } #endregion #region Outgoing Packets public void SendRegionInfoPacketToAll() { // Scene.ForEachRootClient(delegate(IClientAPI client) Scene.ForEachClient(delegate(IClientAPI client) { HandleRegionInfoRequest(client); }); } public void SendRegionHandshake(IClientAPI remoteClient) { remoteClient.SendRegionHandshake(); } public void HandleEstateChangeInfo(IClientAPI remoteClient, UUID invoice, UUID senderID, UInt32 parms1, UInt32 parms2) { bool lastallowEnvOvr = Scene.RegionInfo.EstateSettings.AllowEnvironmentOverride; if ((parms1 & 0x00008000) != 0) Scene.RegionInfo.EstateSettings.PublicAccess = true; else Scene.RegionInfo.EstateSettings.PublicAccess = false; // taxfree is now !AllowAccessOverride (note the negate) if ((parms1 & 0x00000020) != 0) Scene.RegionInfo.EstateSettings.TaxFree = false; else Scene.RegionInfo.EstateSettings.TaxFree = true; if ((parms1 & 0x00000200) != 0) Scene.RegionInfo.EstateSettings.AllowEnvironmentOverride = true; else Scene.RegionInfo.EstateSettings.AllowEnvironmentOverride = 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; // no longer in used, may be reassigned if ((parms1 & 0x01000000) != 0) Scene.RegionInfo.EstateSettings.DenyIdentified = true; else Scene.RegionInfo.EstateSettings.DenyIdentified = false; // no longer in used, may be reassigned if ((parms1 & 0x02000000) != 0) Scene.RegionInfo.EstateSettings.DenyTransacted = true; else Scene.RegionInfo.EstateSettings.DenyTransacted = false; if ((parms1 & 0x10000000) != 0) Scene.RegionInfo.EstateSettings.AllowVoice = true; else Scene.RegionInfo.EstateSettings.AllowVoice = false; if ((parms1 & 0x40000000) != 0) Scene.RegionInfo.EstateSettings.DenyMinors = true; else Scene.RegionInfo.EstateSettings.DenyMinors = false; Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); if (lastallowEnvOvr && Scene.LandChannel != null && !Scene.RegionInfo.EstateSettings.AllowEnvironmentOverride) { Scene.ClearAllParcelEnvironments(); } TriggerEstateInfoChange(); SendDetailedEstateData(remoteClient, invoice); } public bool handleEstateChangeInfoCap(string estateName, UUID invoice, bool externallyVisible, bool allowDirectTeleport, bool denyAnonymous, bool denyAgeUnverified, bool alloVoiceChat, bool overridePublicAccess, bool allowEnvironmentOverride) { bool lastallowEnvOvr = Scene.RegionInfo.EstateSettings.AllowEnvironmentOverride; Scene.RegionInfo.EstateSettings.PublicAccess = externallyVisible; Scene.RegionInfo.EstateSettings.AllowDirectTeleport = allowDirectTeleport; Scene.RegionInfo.EstateSettings.DenyAnonymous = denyAnonymous; Scene.RegionInfo.EstateSettings.AllowVoice = alloVoiceChat; // taxfree is now !AllowAccessOverride Scene.RegionInfo.EstateSettings.TaxFree = overridePublicAccess; Scene.RegionInfo.EstateSettings.DenyMinors = denyAgeUnverified; Scene.RegionInfo.EstateSettings.AllowEnvironmentOverride = allowEnvironmentOverride; Scene.EstateDataService.StoreEstateSettings(Scene.RegionInfo.EstateSettings); if(lastallowEnvOvr && !allowEnvironmentOverride) Scene.ClearAllParcelEnvironments(); TriggerEstateInfoChange(); return true; } #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, false, //Scene.RegionInfo.EstateSettings.FixedSun, false, (float)Scene.RegionInfo.EstateSettings.SunPosition); // sendRegionInfoPacketToAll(); already done by setRegionTerrainSettings } #endregion private void EventManager_OnNewClient(IClientAPI client) { client.OnDetailedEstateDataRequest += ClientSendDetailedEstateData; client.OnSetEstateFlagsRequest += EstateSetRegionInfoHandler; 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; } public uint GetEstateFlags() { RegionFlags flags = RegionFlags.None; if (Scene.RegionInfo.EstateSettings.AllowLandmark) flags |= RegionFlags.AllowLandmark; if (Scene.RegionInfo.EstateSettings.AllowSetHome) flags |= RegionFlags.AllowSetHome; if (Scene.RegionInfo.EstateSettings.ResetHomeOnTeleport) flags |= RegionFlags.ResetHomeOnTeleport; //if (Scene.RegionInfo.EstateSettings.FixedSun) // flags |= RegionFlags.SunFixed; if (!Scene.RegionInfo.EstateSettings.TaxFree) // this is now wrong means !ALLOW_ACCESS_OVERRIDE flags |= RegionFlags.AllowParcelAccessOverride; if (Scene.RegionInfo.EstateSettings.PublicAccess) //?? flags |= (RegionFlags.PublicAllowed | RegionFlags.ExternallyVisible); if (Scene.RegionInfo.EstateSettings.BlockDwell) flags |= RegionFlags.BlockDwell; if (Scene.RegionInfo.EstateSettings.AllowDirectTeleport) flags |= RegionFlags.AllowDirectTeleport; if (Scene.RegionInfo.EstateSettings.EstateSkipScripts) flags |= RegionFlags.EstateSkipScripts; if (Scene.RegionInfo.EstateSettings.DenyAnonymous) flags |= RegionFlags.DenyAnonymous; if (Scene.RegionInfo.EstateSettings.DenyIdentified) // unused? flags |= RegionFlags.DenyIdentified; if (Scene.RegionInfo.EstateSettings.DenyTransacted) // unused? flags |= RegionFlags.DenyTransacted; if (Scene.RegionInfo.EstateSettings.AllowParcelChanges) flags |= RegionFlags.AllowParcelChanges; if (Scene.RegionInfo.EstateSettings.AbuseEmailToEstateOwner) // now is block fly flags |= RegionFlags.AbuseEmailToEstateOwner; if (Scene.RegionInfo.EstateSettings.AllowVoice) flags |= RegionFlags.AllowVoice; if (Scene.RegionInfo.EstateSettings.DenyMinors) flags |= RegionFlags.DenyAgeUnverified; if (Scene.RegionInfo.EstateSettings.AllowEnvironmentOverride) flags |= RegionFlags.AllowEnvironmentOverride; return (uint)flags; } public void TriggerEstateMessage(UUID fromID, string fromName, string message) { OnEstateMessage?.Invoke(Scene.RegionInfo.RegionID, fromID, fromName, message); } private void SendTelehubInfo(IClientAPI client) { RegionSettings settings = this.Scene.RegionInfo.RegionSettings; SceneObjectGroup telehub = null; if (!settings.TelehubObject.IsZero() && (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()); } } } }