diff options
Diffstat (limited to 'OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs')
-rw-r--r-- | OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs | 287 |
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.IO; | ||
31 | using System.Net.Sockets; | ||
32 | using System.Reflection; | ||
33 | using System.Text.RegularExpressions; | ||
34 | using System.Threading; | ||
35 | using OpenMetaverse; | ||
36 | using log4net; | ||
37 | using Nini.Config; | ||
38 | using OpenSim.Framework; | ||
39 | using OpenSim.Region.Framework.Interfaces; | ||
40 | using OpenSim.Region.Framework.Scenes; | ||
41 | |||
42 | namespace 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 | } | ||