OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
PrimLimitsModule.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections.Generic;
30 using System.Linq;
31 using System.Reflection;
32 using log4net;
33 using Mono.Addins;
34 using Nini.Config;
35 using OpenMetaverse;
36 using OpenSim.Framework;
37 using OpenSim.Region.Framework.Interfaces;
38 using OpenSim.Region.Framework.Scenes;
39 
40 namespace OpenSim.Region.OptionalModules
41 {
48  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PrimLimitsModule")]
50  {
52  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53  private bool m_enabled;
54 
55  public string Name { get { return "PrimLimitsModule"; } }
56 
57  public Type ReplaceableInterface { get { return null; } }
58 
59  public void Initialise(IConfigSource config)
60  {
61  string permissionModules = Util.GetConfigVarFromSections<string>(config, "permissionmodules",
62  new string[] { "Startup", "Permissions" }, "DefaultPermissionsModule");
63 
64  List<string> modules = new List<string>(permissionModules.Split(',').Select(m => m.Trim()));
65 
66  if(!modules.Contains("PrimLimitsModule"))
67  return;
68 
69  m_log.DebugFormat("[PRIM LIMITS]: Initialized module");
70  m_enabled = true;
71  }
72 
73  public void Close()
74  {
75  }
76 
77  public void AddRegion(Scene scene)
78  {
79  if (!m_enabled)
80  {
81  return;
82  }
83  scene.Permissions.OnRezObject += CanRezObject;
84  scene.Permissions.OnObjectEntry += CanObjectEnter;
85  scene.Permissions.OnDuplicateObject += CanDuplicateObject;
86 
87  m_log.DebugFormat("[PRIM LIMITS]: Region {0} added", scene.RegionInfo.RegionName);
88  }
89 
90  public void RemoveRegion(Scene scene)
91  {
92  if (m_enabled)
93  {
94  return;
95  }
96 
97  scene.Permissions.OnRezObject -= CanRezObject;
98  scene.Permissions.OnObjectEntry -= CanObjectEnter;
99  scene.Permissions.OnDuplicateObject -= CanDuplicateObject;
100  }
101 
102  public void RegionLoaded(Scene scene)
103  {
104  m_dialogModule = scene.RequestModuleInterface<IDialogModule>();
105  }
106 
107  private bool CanRezObject(int objectCount, UUID ownerID, Vector3 objectPosition, Scene scene)
108  {
109  ILandObject lo = scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y);
110 
111  string response = DoCommonChecks(objectCount, ownerID, lo, scene);
112 
113  if (response != null)
114  {
115  m_dialogModule.SendAlertToUser(ownerID, response);
116  return false;
117  }
118  return true;
119  }
120 
121  //OnDuplicateObject
122  private bool CanDuplicateObject(int objectCount, UUID objectID, UUID ownerID, Scene scene, Vector3 objectPosition)
123  {
124  ILandObject lo = scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y);
125 
126  string response = DoCommonChecks(objectCount, ownerID, lo, scene);
127 
128  if (response != null)
129  {
130  m_dialogModule.SendAlertToUser(ownerID, response);
131  return false;
132  }
133  return true;
134  }
135 
136  private bool CanObjectEnter(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene)
137  {
138  if (newPoint.X < -1f || newPoint.X > (scene.RegionInfo.RegionSizeX + 1) ||
139  newPoint.Y < -1f || newPoint.Y > (scene.RegionInfo.RegionSizeY) )
140  return true;
141 
142  SceneObjectPart obj = scene.GetSceneObjectPart(objectID);
143 
144  if (obj == null)
145  return false;
146 
147  // Prim counts are determined by the location of the root prim. if we're
148  // moving a child prim, just let it pass
149  if (!obj.IsRoot)
150  {
151  return true;
152  }
153 
154  ILandObject newParcel = scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y);
155 
156  if (newParcel == null)
157  return true;
158 
159  Vector3 oldPoint = obj.GroupPosition;
160  ILandObject oldParcel = scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y);
161 
162  // The prim hasn't crossed a region boundry so we don't need to worry
163  // about prim counts here
164  if(oldParcel != null && oldParcel.Equals(newParcel))
165  {
166  return true;
167  }
168 
169  int objectCount = obj.ParentGroup.PrimCount;
170  int usedPrims = newParcel.PrimCounts.Total;
171  int simulatorCapacity = newParcel.GetSimulatorMaxPrimCount();
172 
173  // TODO: Add Special Case here for temporary prims
174 
175  string response = DoCommonChecks(objectCount, obj.OwnerID, newParcel, scene);
176 
177  if (response != null)
178  {
179  m_dialogModule.SendAlertToUser(obj.OwnerID, response);
180  return false;
181  }
182  return true;
183  }
184 
185  private string DoCommonChecks(int objectCount, UUID ownerID, ILandObject lo, Scene scene)
186  {
187  string response = null;
188 
189  int simulatorCapacity = lo.GetSimulatorMaxPrimCount();
190  if ((objectCount + lo.PrimCounts.Total) > simulatorCapacity)
191  {
192  response = "Unable to rez object because the parcel is too full";
193  }
194  else
195  {
196  int maxPrimsPerUser = scene.RegionInfo.MaxPrimsPerUser;
197  if (maxPrimsPerUser >= 0)
198  {
199  // per-user prim limit is set
200  if (ownerID != lo.LandData.OwnerID || lo.LandData.IsGroupOwned)
201  {
202  // caller is not the sole Parcel owner
203  EstateSettings estateSettings = scene.RegionInfo.EstateSettings;
204  if (ownerID != estateSettings.EstateOwner)
205  {
206  // caller is NOT the Estate owner
207  List<UUID> mgrs = new List<UUID>(estateSettings.EstateManagers);
208  if (!mgrs.Contains(ownerID))
209  {
210  // caller is not an Estate Manager
211  if ((lo.PrimCounts.Users[ownerID] + objectCount) > maxPrimsPerUser)
212  {
213  response = "Unable to rez object because you have reached your limit";
214  }
215  }
216  }
217  }
218  }
219  }
220  return response;
221  }
222  }
223 }
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
uint RegionSizeX
X dimension of the region.
Definition: RegionInfo.cs:161
IPrimCounts PrimCounts
Prim counts for this land object.
Definition: ILandObject.cs:50
uint RegionSizeY
X dimension of the region.
Definition: RegionInfo.cs:169
int Total
Total prims on the parcel.
Definition: IPrimCounts.cs:57
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
IUserPrimCounts Users
Prims per individual users.
Definition: IPrimCounts.cs:67
void Initialise(IConfigSource config)
This is called to initialize the region module. For shared modules, this is called exactly once...
bool IsGroupOwned
Returns true if the Land Parcel is owned by a group
Definition: LandData.cs:357
UUID OwnerID
Owner Avatar or Group of the parcel. Naturally, all land masses must be owned by someone ...
Definition: LandData.cs:551