OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
NPCModule.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.Reflection;
31 using System.Threading;
33 
34 using log4net;
35 using Nini.Config;
36 using Mono.Addins;
37 using OpenMetaverse;
38 
39 using OpenSim.Region.Framework.Interfaces;
40 using OpenSim.Region.Framework.Scenes;
41 using OpenSim.Framework;
42 using OpenSim.Services.Interfaces;
43 
44 namespace OpenSim.Region.OptionalModules.World.NPC
45 {
46  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "NPCModule")]
48  {
49  private static readonly ILog m_log = LogManager.GetLogger(
50  MethodBase.GetCurrentMethod().DeclaringType);
51 
52  private Dictionary<UUID, NPCAvatar> m_avatars =
53  new Dictionary<UUID, NPCAvatar>();
54 
55 
56 
57  private NPCOptionsFlags m_NPCOptionFlags;
58  public NPCOptionsFlags NPCOptionFlags {get {return m_NPCOptionFlags;}}
59 
60  public bool Enabled { get; private set; }
61 
62  public void Initialise(IConfigSource source)
63  {
64  IConfig config = source.Configs["NPC"];
65 
66  Enabled = (config != null && config.GetBoolean("Enabled", false));
67  m_NPCOptionFlags = NPCOptionsFlags.None;
68  if(Enabled)
69  {
70  if(config.GetBoolean("AllowNotOwned", true))
71  m_NPCOptionFlags |= NPCOptionsFlags.AllowNotOwned;
72 
73  if(config.GetBoolean("AllowSenseAsAvatar", true))
74  m_NPCOptionFlags |= NPCOptionsFlags.AllowSenseAsAvatar;
75 
76  if(config.GetBoolean("AllowCloneOtherAvatars", true))
77  m_NPCOptionFlags |= NPCOptionsFlags.AllowCloneOtherAvatars;
78 
79  if(config.GetBoolean("NoNPCGroup", true))
80  m_NPCOptionFlags |= NPCOptionsFlags.NoNPCGroup;
81  }
82  }
83 
84  public void AddRegion(Scene scene)
85  {
86  if (Enabled)
87  scene.RegisterModuleInterface<INPCModule>(this);
88  }
89 
90  public void RegionLoaded(Scene scene)
91  {
92  }
93 
94  public void PostInitialise()
95  {
96  }
97 
98  public void RemoveRegion(Scene scene)
99  {
100  scene.UnregisterModuleInterface<INPCModule>(this);
101  }
102 
103  public void Close()
104  {
105  }
106 
107  public string Name
108  {
109  get { return "NPCModule"; }
110  }
111 
112  public Type ReplaceableInterface { get { return null; } }
113 
114  public bool IsNPC(UUID agentId, Scene scene)
115  {
116  // FIXME: This implementation could not just use the
117  // ScenePresence.PresenceType (and callers could inspect that
118  // directly).
119  ScenePresence sp = scene.GetScenePresence(agentId);
120  if (sp == null || sp.IsChildAgent)
121  return false;
122 
123  lock (m_avatars)
124  return m_avatars.ContainsKey(agentId);
125  }
126 
127  public bool SetNPCAppearance(UUID agentId,
128  AvatarAppearance appearance, Scene scene)
129  {
130  ScenePresence npc = scene.GetScenePresence(agentId);
131  if (npc == null || npc.IsChildAgent)
132  return false;
133 
134  lock (m_avatars)
135  if (!m_avatars.ContainsKey(agentId))
136  return false;
137 
138  // Delete existing npc attachments
139  if(scene.AttachmentsModule != null)
140  scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false);
141 
142  // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet
143  // since it doesn't transfer attachments
144  AvatarAppearance npcAppearance = new AvatarAppearance(appearance,
145  true);
146  npc.Appearance = npcAppearance;
147 
148  // Rez needed npc attachments
149  if (scene.AttachmentsModule != null)
150  scene.AttachmentsModule.RezAttachments(npc);
151 
152  IAvatarFactoryModule module =
153  scene.RequestModuleInterface<IAvatarFactoryModule>();
154  module.SendAppearance(npc.UUID);
155 
156  return true;
157  }
158 
159  public UUID CreateNPC(string firstname, string lastname,
160  Vector3 position, UUID owner, bool senseAsAgent, Scene scene,
161  AvatarAppearance appearance)
162  {
163  return CreateNPC(firstname, lastname, position, UUID.Zero, owner, senseAsAgent, scene, appearance);
164  }
165 
166  public UUID CreateNPC(string firstname, string lastname,
167  Vector3 position, UUID agentID, UUID owner, bool senseAsAgent, Scene scene,
168  AvatarAppearance appearance)
169  {
170  NPCAvatar npcAvatar = null;
171 
172  try
173  {
174  if (agentID == UUID.Zero)
175  npcAvatar = new NPCAvatar(firstname, lastname, position,
176  owner, senseAsAgent, scene);
177  else
178  npcAvatar = new NPCAvatar(firstname, lastname, agentID, position,
179  owner, senseAsAgent, scene);
180  }
181  catch (Exception e)
182  {
183  m_log.Info("[NPC MODULE]: exception creating NPC avatar: " + e.ToString());
184  return UUID.Zero;
185  }
186 
187  npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0,
188  int.MaxValue);
189 
190 // m_log.DebugFormat(
191 // "[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}",
192 // firstname, lastname, npcAvatar.AgentId, owner, senseAsAgent, position, scene.RegionInfo.RegionName);
193 
195  acd.AgentID = npcAvatar.AgentId;
196  acd.firstname = firstname;
197  acd.lastname = lastname;
198  acd.ServiceURLs = new Dictionary<string, object>();
199 
200  AvatarAppearance npcAppearance = new AvatarAppearance(appearance, true);
201  acd.Appearance = npcAppearance;
202 
203  /*
204  for (int i = 0;
205  i < acd.Appearance.Texture.FaceTextures.Length; i++)
206  {
207  m_log.DebugFormat(
208  "[NPC MODULE]: NPC avatar {0} has texture id {1} : {2}",
209  acd.AgentID, i,
210  acd.Appearance.Texture.FaceTextures[i]);
211  }
212  */
213 
214 // ManualResetEvent ev = new ManualResetEvent(false);
215 
216 // Util.FireAndForget(delegate(object x) {
217  lock (m_avatars)
218  {
219  scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
220  scene.AddNewAgent(npcAvatar, PresenceType.Npc);
221 
222  ScenePresence sp;
223  if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
224  {
225 
226  sp.CompleteMovement(npcAvatar, false);
227  m_avatars.Add(npcAvatar.AgentId, npcAvatar);
228 // m_log.DebugFormat("[NPC MODULE]: Created NPC {0} {1}", npcAvatar.AgentId, sp.Name);
229  }
230  }
231 // ev.Set();
232 // });
233 
234 // ev.WaitOne();
235 
236 // m_log.DebugFormat("[NPC MODULE]: Created NPC with id {0}", npcAvatar.AgentId);
237 
238  return npcAvatar.AgentId;
239  }
240 
241  public bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos,
242  bool noFly, bool landAtTarget, bool running)
243  {
244  lock (m_avatars)
245  {
246  if (m_avatars.ContainsKey(agentID))
247  {
248  ScenePresence sp;
249  if (scene.TryGetScenePresence(agentID, out sp))
250  {
251  if (sp.IsSatOnObject || sp.SitGround)
252  return false;
253 
254 // m_log.DebugFormat(
255 // "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
256 // sp.Name, pos, scene.RegionInfo.RegionName,
257 // noFly, landAtTarget);
258 
259  sp.MoveToTarget(pos, noFly, landAtTarget);
260  sp.SetAlwaysRun = running;
261 
262  return true;
263  }
264  }
265  }
266 
267  return false;
268  }
269 
270  public bool StopMoveToTarget(UUID agentID, Scene scene)
271  {
272  lock (m_avatars)
273  {
274  if (m_avatars.ContainsKey(agentID))
275  {
276  ScenePresence sp;
277  if (scene.TryGetScenePresence(agentID, out sp))
278  {
279  sp.Velocity = Vector3.Zero;
280  sp.ResetMoveToTarget();
281 
282  return true;
283  }
284  }
285  }
286 
287  return false;
288  }
289 
290  public bool Say(UUID agentID, Scene scene, string text)
291  {
292  return Say(agentID, scene, text, 0);
293  }
294 
295  public bool Say(UUID agentID, Scene scene, string text, int channel)
296  {
297  lock (m_avatars)
298  {
299  if (m_avatars.ContainsKey(agentID))
300  {
301  m_avatars[agentID].Say(channel, text);
302 
303  return true;
304  }
305  }
306 
307  return false;
308  }
309 
310  public bool Shout(UUID agentID, Scene scene, string text, int channel)
311  {
312  lock (m_avatars)
313  {
314  if (m_avatars.ContainsKey(agentID))
315  {
316  m_avatars[agentID].Shout(channel, text);
317 
318  return true;
319  }
320  }
321 
322  return false;
323  }
324 
325  public bool Sit(UUID agentID, UUID partID, Scene scene)
326  {
327  lock (m_avatars)
328  {
329  if (m_avatars.ContainsKey(agentID))
330  {
331  ScenePresence sp;
332  if (scene.TryGetScenePresence(agentID, out sp))
333  {
334  sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero);
335 
336  return true;
337  }
338  }
339  }
340 
341  return false;
342  }
343 
344  public bool Whisper(UUID agentID, Scene scene, string text,
345  int channel)
346  {
347  lock (m_avatars)
348  {
349  if (m_avatars.ContainsKey(agentID))
350  {
351  m_avatars[agentID].Whisper(channel, text);
352 
353  return true;
354  }
355  }
356 
357  return false;
358  }
359 
360  public bool Stand(UUID agentID, Scene scene)
361  {
362  lock (m_avatars)
363  {
364  if (m_avatars.ContainsKey(agentID))
365  {
366  ScenePresence sp;
367  if (scene.TryGetScenePresence(agentID, out sp))
368  {
369  sp.StandUp();
370 
371  return true;
372  }
373  }
374  }
375 
376  return false;
377  }
378 
379  public bool Touch(UUID agentID, UUID objectID)
380  {
381  lock (m_avatars)
382  {
383  if (m_avatars.ContainsKey(agentID))
384  return m_avatars[agentID].Touch(objectID);
385 
386  return false;
387  }
388  }
389 
390  public UUID GetOwner(UUID agentID)
391  {
392  lock (m_avatars)
393  {
394  NPCAvatar av;
395  if (m_avatars.TryGetValue(agentID, out av))
396  return av.OwnerID;
397  }
398 
399  return UUID.Zero;
400  }
401 
402  public INPC GetNPC(UUID agentID, Scene scene)
403  {
404  lock (m_avatars)
405  {
406  if (m_avatars.ContainsKey(agentID))
407  return m_avatars[agentID];
408  else
409  return null;
410  }
411  }
412 
413  public bool DeleteNPC(UUID agentID, Scene scene)
414  {
415  bool doRemove = false;
416  NPCAvatar av;
417  lock (m_avatars)
418  {
419  if (m_avatars.TryGetValue(agentID, out av))
420  {
421  /*
422  m_log.DebugFormat("[NPC MODULE]: Found {0} {1} to remove",
423  agentID, av.Name);
424  */
425  doRemove = true;
426  }
427  }
428 
429  if (doRemove)
430  {
431  scene.CloseAgent(agentID, false);
432  lock (m_avatars)
433  {
434  m_avatars.Remove(agentID);
435  }
436  m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}",
437  agentID, av.Name);
438  return true;
439  }
440  /*
441  m_log.DebugFormat("[NPC MODULE]: Could not find {0} to remove",
442  agentID);
443  */
444  return false;
445  }
446 
447  public bool CheckPermissions(UUID npcID, UUID callerID)
448  {
449  lock (m_avatars)
450  {
451  NPCAvatar av;
452  if (m_avatars.TryGetValue(npcID, out av))
453  {
454  if (npcID == callerID)
455  return true;
456  return CheckPermissions(av, callerID);
457  }
458  else
459  {
460  return false;
461  }
462  }
463  }
464 
478  private bool CheckPermissions(NPCAvatar av, UUID callerID)
479  {
480  return callerID == UUID.Zero || av.OwnerID == UUID.Zero ||
481  av.OwnerID == callerID || av.AgentId == callerID;
482  }
483  }
484 }
bool DeleteNPC(UUID agentID, Scene scene)
Delete an NPC.
Definition: NPCModule.cs:413
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
Definition: NPCModule.cs:84
INPC GetNPC(UUID agentID, Scene scene)
Get the NPC.
Definition: NPCModule.cs:402
void PostInitialise()
This is called exactly once after all the shared region-modules have been instanciated and IRegionMod...
Definition: NPCModule.cs:94
bool Stand(UUID agentID, Scene scene)
Stand a sitting NPC.
Definition: NPCModule.cs:360
bool Say(UUID agentID, Scene scene, string text, int channel)
Get the NPC to say something.
Definition: NPCModule.cs:295
bool CheckPermissions(UUID npcID, UUID callerID)
Check if the caller has permission to manipulate the given NPC.
Definition: NPCModule.cs:447
Contains the Avatar's Appearance and methods to manipulate the appearance.
void Initialise(IConfigSource source)
This is called to initialize the region module. For shared modules, this is called exactly once...
Definition: NPCModule.cs:62
Temporary interface. More methods to come at some point to make NPCs more object oriented rather than...
Definition: INPCModule.cs:50
System.Timers.Timer Timer
bool StopMoveToTarget(UUID agentID, Scene scene)
Stop the NPC's current movement.
Definition: NPCModule.cs:270
bool IsNPC(UUID agentId, Scene scene)
Check if the agent is an NPC.
Definition: NPCModule.cs:114
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
Definition: NPCModule.cs:98
Circuit data for an agent. Connection information shared between regions that accept UDP connections ...
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
Definition: NPCModule.cs:90
IAttachmentsModule AttachmentsModule
Definition: Scene.cs:771
bool Touch(UUID agentID, UUID objectID)
Get the NPC to touch an object.
Definition: NPCModule.cs:379
bool SetNPCAppearance(UUID agentId, AvatarAppearance appearance, Scene scene)
Set the appearance for an NPC.
Definition: NPCModule.cs:127
override bool TryGetScenePresence(UUID agentID, out ScenePresence sp)
Try to get a scene presence from the scene
Definition: Scene.cs:5401
bool Whisper(UUID agentID, Scene scene, string text, int channel)
Get the NPC to whisper something.
Definition: NPCModule.cs:344
System.Timers.Timer Timer
Definition: NPCModule.cs:32
UUID CreateNPC(string firstname, string lastname, Vector3 position, UUID owner, bool senseAsAgent, Scene scene, AvatarAppearance appearance)
Create an NPC
Definition: NPCModule.cs:159
bool Say(UUID agentID, Scene scene, string text)
Get the NPC to say something.
Definition: NPCModule.cs:290
bool Sit(UUID agentID, UUID partID, Scene scene)
Sit the NPC.
Definition: NPCModule.cs:325
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
Definition: NPCModule.cs:103
UUID GetOwner(UUID agentID)
Get the owner of a NPC
Definition: NPCModule.cs:390
UUID CreateNPC(string firstname, string lastname, Vector3 position, UUID agentID, UUID owner, bool senseAsAgent, Scene scene, AvatarAppearance appearance)
Create an NPC with a user-supplied agentID
Definition: NPCModule.cs:166
bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos, bool noFly, bool landAtTarget, bool running)
Move an NPC to a target over time.
Definition: NPCModule.cs:241
bool Shout(UUID agentID, Scene scene, string text, int channel)
Get the NPC to shout something.
Definition: NPCModule.cs:310