aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs')
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs287
1 files changed, 0 insertions, 287 deletions
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs
deleted file mode 100644
index f234b75..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs
+++ /dev/null
@@ -1,287 +0,0 @@
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 OpenSim 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
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Net.Sockets;
32using System.Reflection;
33using System.Text.RegularExpressions;
34using System.Threading;
35using OpenMetaverse;
36using log4net;
37using Nini.Config;
38using OpenSim.Framework;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Region.Environment.Modules.Avatar.Chat
43{
44 public class ChatModule : IRegionModule
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private const int DEBUG_CHANNEL = 2147483647;
50
51 private bool m_enabled = true;
52 private int m_saydistance = 30;
53 private int m_shoutdistance = 100;
54 private int m_whisperdistance = 10;
55 private List<Scene> m_scenes = new List<Scene>();
56
57 internal object m_syncInit = new object();
58
59 #region IRegionModule Members
60 public virtual void Initialise(Scene scene, IConfigSource config)
61 {
62 // wrap this in a try block so that defaults will work if
63 // the config file doesn't specify otherwise.
64 try
65 {
66 m_enabled = config.Configs["Chat"].GetBoolean("enabled", m_enabled);
67 if (!m_enabled) return;
68
69 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
70 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
71 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
72 }
73 catch (Exception)
74 {
75 }
76
77 lock (m_syncInit)
78 {
79 if (!m_scenes.Contains(scene))
80 {
81 m_scenes.Add(scene);
82 scene.EventManager.OnNewClient += OnNewClient;
83 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
84 scene.EventManager.OnChatBroadcast += OnChatBroadcast;
85 }
86 }
87
88 m_log.InfoFormat("[CHAT] initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName,
89 m_whisperdistance, m_saydistance, m_shoutdistance);
90 }
91 public virtual void PostInitialise()
92 {
93 }
94
95 public virtual void Close()
96 {
97 }
98
99 public virtual string Name
100 {
101 get { return "ChatModule"; }
102 }
103
104 public virtual bool IsSharedModule
105 {
106 get { return true; }
107 }
108
109 #endregion
110
111
112 public virtual void OnNewClient(IClientAPI client)
113 {
114 client.OnChatFromClient += OnChatFromClient;
115 }
116
117 protected OSChatMessage FixPositionOfChatMessage(OSChatMessage c)
118 {
119 ScenePresence avatar;
120 Scene scene = (Scene)c.Scene;
121 if ((avatar = scene.GetScenePresence(c.Sender.AgentId)) != null)
122 c.Position = avatar.AbsolutePosition;
123
124 return c;
125 }
126
127 public virtual void OnChatFromClient(Object sender, OSChatMessage c)
128 {
129 c = FixPositionOfChatMessage(c);
130
131 // redistribute to interested subscribers
132 Scene scene = (Scene)c.Scene;
133 scene.EventManager.TriggerOnChatFromClient(sender, c);
134
135 // early return if not on public or debug channel
136 if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return;
137
138 // sanity check:
139 if (c.Sender == null)
140 {
141 m_log.ErrorFormat("[CHAT] OnChatFromClient from {0} has empty Sender field!", sender);
142 return;
143 }
144
145 DeliverChatToAvatars(ChatSourceType.Agent, c);
146 }
147
148 public virtual void OnChatFromWorld(Object sender, OSChatMessage c)
149 {
150 // early return if not on public or debug channel
151 if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return;
152
153 DeliverChatToAvatars(ChatSourceType.Object, c);
154 }
155
156 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
157 {
158 string fromName = c.From;
159 UUID fromID = UUID.Zero;
160 string message = c.Message;
161 IScene scene = c.Scene;
162 Vector3 fromPos = c.Position;
163 Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize,
164 scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
165
166 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel;
167
168 switch (sourceType)
169 {
170 case ChatSourceType.Agent:
171 if (!(scene is Scene))
172 {
173 m_log.WarnFormat("[CHAT]: scene {0} is not a Scene object, cannot obtain scene presence for {1}",
174 scene.RegionInfo.RegionName, c.Sender.AgentId);
175 return;
176 }
177 ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId);
178 fromPos = avatar.AbsolutePosition;
179 fromName = avatar.Name;
180 fromID = c.Sender.AgentId;
181
182 break;
183
184 case ChatSourceType.Object:
185 fromID = c.SenderUUID;
186
187 break;
188 }
189
190 // TODO: iterate over message
191 if (message.Length >= 1000) // libomv limit
192 message = message.Substring(0, 1000);
193
194 // m_log.DebugFormat("[CHAT]: DCTA: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, c.Type, sourceType);
195
196 foreach (Scene s in m_scenes)
197 {
198 s.ForEachScenePresence(delegate(ScenePresence presence)
199 {
200 TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName,
201 c.Type, message, sourceType);
202 });
203 }
204 }
205
206
207 static private Vector3 CenterOfRegion = new Vector3(128, 128, 30);
208 public virtual void OnChatBroadcast(Object sender, OSChatMessage c)
209 {
210 // unless the chat to be broadcast is of type Region, we
211 // drop it if its channel is neither 0 nor DEBUG_CHANNEL
212 if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL && c.Type != ChatTypeEnum.Region) return;
213
214 ChatTypeEnum cType = c.Type;
215 if (c.Channel == DEBUG_CHANNEL)
216 cType = ChatTypeEnum.DebugChannel;
217
218 if (cType == ChatTypeEnum.Region)
219 cType = ChatTypeEnum.Say;
220
221 if (c.Message.Length > 1100)
222 c.Message = c.Message.Substring(0, 1000);
223
224 // broadcast chat works by redistributing every incoming chat
225 // message to each avatar in the scene.
226 string fromName = c.From;
227
228 UUID fromID = UUID.Zero;
229 ChatSourceType sourceType = ChatSourceType.Object;
230 if (null != c.Sender)
231 {
232 ScenePresence avatar = (c.Scene as Scene).GetScenePresence(c.Sender.AgentId);
233 fromID = c.Sender.AgentId;
234 fromName = avatar.Name;
235 sourceType = ChatSourceType.Agent;
236 }
237
238 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
239
240 ((Scene)c.Scene).ForEachScenePresence(
241 delegate(ScenePresence presence)
242 {
243 // ignore chat from child agents
244 if (presence.IsChildAgent) return;
245
246 IClientAPI client = presence.ControllingClient;
247
248 // don't forward SayOwner chat from objects to
249 // non-owner agents
250 if ((c.Type == ChatTypeEnum.Owner) &&
251 (null != c.SenderObject) &&
252 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
253 return;
254
255 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID,
256 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
257 });
258 }
259
260
261 protected virtual void TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos,
262 UUID fromAgentID, string fromName, ChatTypeEnum type,
263 string message, ChatSourceType src)
264 {
265 // don't send stuff to child agents
266 if (presence.IsChildAgent) return;
267
268 Vector3 fromRegionPos = fromPos + regionPos;
269 Vector3 toRegionPos = presence.AbsolutePosition +
270 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
271 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
272
273 int dis = Math.Abs((int) Util.GetDistanceTo(toRegionPos, fromRegionPos));
274
275 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
276 type == ChatTypeEnum.Say && dis > m_saydistance ||
277 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
278 {
279 return;
280 }
281
282 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView
283 presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName,
284 fromAgentID,(byte)src,(byte)ChatAudibleLevel.Fully);
285 }
286 }
287}