diff options
author | Adam Frisby | 2008-04-30 21:16:36 +0000 |
---|---|---|
committer | Adam Frisby | 2008-04-30 21:16:36 +0000 |
commit | f5c312bc3c2567449c7268a54a08a54119f58d53 (patch) | |
tree | 424668a4bbec6873ebc5b8256f3671db102f5e9c /OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs | |
parent | * Adds the AuthbuyerID field to sqlite and makes use of it. (diff) | |
download | opensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.zip opensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.tar.gz opensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.tar.bz2 opensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.tar.xz |
* Refactored Environment/Modules directory - modules now reside in their own directory with any associated module-specific classes.
* Each module directory is currently inside one of the following category folders: Agent (Anything relating to do with Client<->Server communications.), Avatar (Anything to do with the avatar or presence inworld), Framework (Classes modules can use), Grid (Grid traffic, new OGS2 grid comms), Scripting (Scripting functions, etc), World (The enrivonment/scene, IE Sun/Tree modules.)
* This should be moved into a seperate project file.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs (renamed from OpenSim/Region/Environment/Modules/ChatModule.cs) | 1662 |
1 files changed, 831 insertions, 831 deletions
diff --git a/OpenSim/Region/Environment/Modules/ChatModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs index 30c1397..1281873 100644 --- a/OpenSim/Region/Environment/Modules/ChatModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs | |||
@@ -1,831 +1,831 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions are met: | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * * Redistributions of source code must retain the above copyright | 7 | * * Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. | 8 | * notice, this list of conditions and the following disclaimer. |
9 | * * Redistributions in binary form must reproduce the above copyright | 9 | * * Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the | 10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. | 11 | * documentation and/or other materials provided with the distribution. |
12 | * * Neither the name of the OpenSim Project nor the | 12 | * * Neither the name of the OpenSim Project nor the |
13 | * names of its contributors may be used to endorse or promote products | 13 | * names of its contributors may be used to endorse or promote products |
14 | * derived from this software without specific prior written permission. | 14 | * derived from this software without specific prior written permission. |
15 | * | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | 16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | 19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 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 | 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 | 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 | 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. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.IO; | 30 | using System.IO; |
31 | using System.Net.Sockets; | 31 | using System.Net.Sockets; |
32 | using System.Reflection; | 32 | using System.Reflection; |
33 | using System.Text.RegularExpressions; | 33 | using System.Text.RegularExpressions; |
34 | using System.Threading; | 34 | using System.Threading; |
35 | using libsecondlife; | 35 | using libsecondlife; |
36 | using log4net; | 36 | using log4net; |
37 | using Nini.Config; | 37 | using Nini.Config; |
38 | using OpenSim.Framework; | 38 | using OpenSim.Framework; |
39 | using OpenSim.Region.Environment.Interfaces; | 39 | using OpenSim.Region.Environment.Interfaces; |
40 | using OpenSim.Region.Environment.Scenes; | 40 | using OpenSim.Region.Environment.Scenes; |
41 | 41 | ||
42 | namespace OpenSim.Region.Environment.Modules | 42 | namespace OpenSim.Region.Environment.Modules.Avatar.Chat |
43 | { | 43 | { |
44 | public class ChatModule : IRegionModule, ISimChat | 44 | public class ChatModule : IRegionModule, ISimChat |
45 | { | 45 | { |
46 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 46 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
47 | 47 | ||
48 | private List<Scene> m_scenes = new List<Scene>(); | 48 | private List<Scene> m_scenes = new List<Scene>(); |
49 | 49 | ||
50 | private int m_whisperdistance = 10; | 50 | private int m_whisperdistance = 10; |
51 | private int m_saydistance = 30; | 51 | private int m_saydistance = 30; |
52 | private int m_shoutdistance = 100; | 52 | private int m_shoutdistance = 100; |
53 | 53 | ||
54 | private IRCChatModule m_irc = null; | 54 | private IRCChatModule m_irc = null; |
55 | 55 | ||
56 | private string m_last_new_user = null; | 56 | private string m_last_new_user = null; |
57 | private string m_last_leaving_user = null; | 57 | private string m_last_leaving_user = null; |
58 | private string m_defaultzone = null; | 58 | private string m_defaultzone = null; |
59 | internal object m_syncInit = new object(); | 59 | internal object m_syncInit = new object(); |
60 | internal object m_syncLogout = new object(); | 60 | internal object m_syncLogout = new object(); |
61 | private Thread m_irc_connector=null; | 61 | private Thread m_irc_connector=null; |
62 | 62 | ||
63 | public void Initialise(Scene scene, IConfigSource config) | 63 | public void Initialise(Scene scene, IConfigSource config) |
64 | { | 64 | { |
65 | lock (m_syncInit) | 65 | lock (m_syncInit) |
66 | { | 66 | { |
67 | if (!m_scenes.Contains(scene)) | 67 | if (!m_scenes.Contains(scene)) |
68 | { | 68 | { |
69 | m_scenes.Add(scene); | 69 | m_scenes.Add(scene); |
70 | scene.EventManager.OnNewClient += NewClient; | 70 | scene.EventManager.OnNewClient += NewClient; |
71 | scene.RegisterModuleInterface<ISimChat>(this); | 71 | scene.RegisterModuleInterface<ISimChat>(this); |
72 | } | 72 | } |
73 | 73 | ||
74 | // wrap this in a try block so that defaults will work if | 74 | // wrap this in a try block so that defaults will work if |
75 | // the config file doesn't specify otherwise. | 75 | // the config file doesn't specify otherwise. |
76 | try | 76 | try |
77 | { | 77 | { |
78 | m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); | 78 | m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); |
79 | m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); | 79 | m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); |
80 | m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); | 80 | m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); |
81 | } | 81 | } |
82 | catch (Exception) | 82 | catch (Exception) |
83 | { | 83 | { |
84 | } | 84 | } |
85 | 85 | ||
86 | try | 86 | try |
87 | { | 87 | { |
88 | m_defaultzone = config.Configs["IRC"].GetString("nick","Sim"); | 88 | m_defaultzone = config.Configs["IRC"].GetString("nick","Sim"); |
89 | } | 89 | } |
90 | catch (Exception) | 90 | catch (Exception) |
91 | { | 91 | { |
92 | } | 92 | } |
93 | 93 | ||
94 | // setup IRC Relay | 94 | // setup IRC Relay |
95 | if (m_irc == null) { m_irc = new IRCChatModule(config); } | 95 | if (m_irc == null) { m_irc = new IRCChatModule(config); } |
96 | if (m_irc_connector == null) | 96 | if (m_irc_connector == null) |
97 | { | 97 | { |
98 | m_irc_connector = new Thread(IRCConnectRun); | 98 | m_irc_connector = new Thread(IRCConnectRun); |
99 | m_irc_connector.Name = "IRCConnectorThread"; | 99 | m_irc_connector.Name = "IRCConnectorThread"; |
100 | m_irc_connector.IsBackground = true; | 100 | m_irc_connector.IsBackground = true; |
101 | } | 101 | } |
102 | } | 102 | } |
103 | } | 103 | } |
104 | 104 | ||
105 | public void PostInitialise() | 105 | public void PostInitialise() |
106 | { | 106 | { |
107 | if (m_irc.Enabled) | 107 | if (m_irc.Enabled) |
108 | { | 108 | { |
109 | try | 109 | try |
110 | { | 110 | { |
111 | //m_irc.Connect(m_scenes); | 111 | //m_irc.Connect(m_scenes); |
112 | if (m_irc_connector == null) | 112 | if (m_irc_connector == null) |
113 | { | 113 | { |
114 | m_irc_connector = new Thread(IRCConnectRun); | 114 | m_irc_connector = new Thread(IRCConnectRun); |
115 | m_irc_connector.Name = "IRCConnectorThread"; | 115 | m_irc_connector.Name = "IRCConnectorThread"; |
116 | m_irc_connector.IsBackground = true; | 116 | m_irc_connector.IsBackground = true; |
117 | } | 117 | } |
118 | if (!m_irc_connector.IsAlive) | 118 | if (!m_irc_connector.IsAlive) |
119 | { | 119 | { |
120 | m_irc_connector.Start(); | 120 | m_irc_connector.Start(); |
121 | ThreadTracker.Add(m_irc_connector); | 121 | ThreadTracker.Add(m_irc_connector); |
122 | } | 122 | } |
123 | } | 123 | } |
124 | catch (Exception) | 124 | catch (Exception) |
125 | { | 125 | { |
126 | } | 126 | } |
127 | } | 127 | } |
128 | } | 128 | } |
129 | 129 | ||
130 | public void Close() | 130 | public void Close() |
131 | { | 131 | { |
132 | m_irc.Close(); | 132 | m_irc.Close(); |
133 | } | 133 | } |
134 | 134 | ||
135 | public string Name | 135 | public string Name |
136 | { | 136 | { |
137 | get { return "ChatModule"; } | 137 | get { return "ChatModule"; } |
138 | } | 138 | } |
139 | 139 | ||
140 | public bool IsSharedModule | 140 | public bool IsSharedModule |
141 | { | 141 | { |
142 | get { return true; } | 142 | get { return true; } |
143 | } | 143 | } |
144 | 144 | ||
145 | public void NewClient(IClientAPI client) | 145 | public void NewClient(IClientAPI client) |
146 | { | 146 | { |
147 | try | 147 | try |
148 | { | 148 | { |
149 | client.OnChatFromViewer += SimChat; | 149 | client.OnChatFromViewer += SimChat; |
150 | 150 | ||
151 | if ((m_irc.Enabled) && (m_irc.Connected)) | 151 | if ((m_irc.Enabled) && (m_irc.Connected)) |
152 | { | 152 | { |
153 | string clientName = client.FirstName + " " + client.LastName; | 153 | string clientName = client.FirstName + " " + client.LastName; |
154 | // handles simple case. May not work for hundred connecting in per second. | 154 | // handles simple case. May not work for hundred connecting in per second. |
155 | // and the NewClients calles getting interleved | 155 | // and the NewClients calles getting interleved |
156 | // but filters out multiple reports | 156 | // but filters out multiple reports |
157 | if (clientName != m_last_new_user) | 157 | if (clientName != m_last_new_user) |
158 | { | 158 | { |
159 | m_last_new_user = clientName; | 159 | m_last_new_user = clientName; |
160 | string clientRegion = FindClientRegion(client.FirstName, client.LastName); | 160 | string clientRegion = FindClientRegion(client.FirstName, client.LastName); |
161 | m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " in "+clientRegion); | 161 | m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " in "+clientRegion); |
162 | } | 162 | } |
163 | } | 163 | } |
164 | client.OnLogout += ClientLoggedOut; | 164 | client.OnLogout += ClientLoggedOut; |
165 | client.OnConnectionClosed += ClientLoggedOut; | 165 | client.OnConnectionClosed += ClientLoggedOut; |
166 | client.OnLogout += ClientLoggedOut; | 166 | client.OnLogout += ClientLoggedOut; |
167 | } | 167 | } |
168 | catch (Exception ex) | 168 | catch (Exception ex) |
169 | { | 169 | { |
170 | m_log.Error("[IRC]: NewClient exception trap:" + ex.ToString()); | 170 | m_log.Error("[IRC]: NewClient exception trap:" + ex.ToString()); |
171 | } | 171 | } |
172 | } | 172 | } |
173 | 173 | ||
174 | public void ClientLoggedOut(IClientAPI client) | 174 | public void ClientLoggedOut(IClientAPI client) |
175 | { | 175 | { |
176 | lock (m_syncLogout) | 176 | lock (m_syncLogout) |
177 | { | 177 | { |
178 | try | 178 | try |
179 | { | 179 | { |
180 | if ((m_irc.Enabled) && (m_irc.Connected)) | 180 | if ((m_irc.Enabled) && (m_irc.Connected)) |
181 | { | 181 | { |
182 | string clientName = client.FirstName + " " + client.LastName; | 182 | string clientName = client.FirstName + " " + client.LastName; |
183 | string clientRegion = FindClientRegion(client.FirstName, client.LastName); | 183 | string clientRegion = FindClientRegion(client.FirstName, client.LastName); |
184 | // handles simple case. May not work for hundred connecting in per second. | 184 | // handles simple case. May not work for hundred connecting in per second. |
185 | // and the NewClients calles getting interleved | 185 | // and the NewClients calles getting interleved |
186 | // but filters out multiple reports | 186 | // but filters out multiple reports |
187 | if (clientName != m_last_leaving_user) | 187 | if (clientName != m_last_leaving_user) |
188 | { | 188 | { |
189 | m_last_leaving_user = clientName; | 189 | m_last_leaving_user = clientName; |
190 | m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " left " + clientRegion); | 190 | m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " left " + clientRegion); |
191 | m_log.Info("[IRC]: IRC watcher notices " + clientName + " left " + clientRegion); | 191 | m_log.Info("[IRC]: IRC watcher notices " + clientName + " left " + clientRegion); |
192 | } | 192 | } |
193 | } | 193 | } |
194 | } | 194 | } |
195 | catch (Exception ex) | 195 | catch (Exception ex) |
196 | { | 196 | { |
197 | m_log.Error("[IRC]: ClientLoggedOut exception trap:" + ex.ToString()); | 197 | m_log.Error("[IRC]: ClientLoggedOut exception trap:" + ex.ToString()); |
198 | } | 198 | } |
199 | } | 199 | } |
200 | } | 200 | } |
201 | 201 | ||
202 | private void TrySendChatMessage(ScenePresence presence, LLVector3 fromPos, LLVector3 regionPos, | 202 | private void TrySendChatMessage(ScenePresence presence, LLVector3 fromPos, LLVector3 regionPos, |
203 | LLUUID fromAgentID, string fromName, ChatTypeEnum type, string message) | 203 | LLUUID fromAgentID, string fromName, ChatTypeEnum type, string message) |
204 | { | 204 | { |
205 | if (!presence.IsChildAgent) | 205 | if (!presence.IsChildAgent) |
206 | { | 206 | { |
207 | LLVector3 fromRegionPos = fromPos + regionPos; | 207 | LLVector3 fromRegionPos = fromPos + regionPos; |
208 | LLVector3 toRegionPos = presence.AbsolutePosition + regionPos; | 208 | LLVector3 toRegionPos = presence.AbsolutePosition + regionPos; |
209 | int dis = Math.Abs((int) Util.GetDistanceTo(toRegionPos, fromRegionPos)); | 209 | int dis = Math.Abs((int) Util.GetDistanceTo(toRegionPos, fromRegionPos)); |
210 | 210 | ||
211 | if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance || | 211 | if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance || |
212 | type == ChatTypeEnum.Say && dis > m_saydistance || | 212 | type == ChatTypeEnum.Say && dis > m_saydistance || |
213 | type == ChatTypeEnum.Shout && dis > m_shoutdistance) | 213 | type == ChatTypeEnum.Shout && dis > m_shoutdistance) |
214 | { | 214 | { |
215 | return; | 215 | return; |
216 | } | 216 | } |
217 | 217 | ||
218 | // TODO: should change so the message is sent through the avatar rather than direct to the ClientView | 218 | // TODO: should change so the message is sent through the avatar rather than direct to the ClientView |
219 | presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, fromAgentID); | 219 | presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, fromAgentID); |
220 | } | 220 | } |
221 | } | 221 | } |
222 | 222 | ||
223 | public void SimChat(Object sender, ChatFromViewerArgs e) | 223 | public void SimChat(Object sender, ChatFromViewerArgs e) |
224 | { | 224 | { |
225 | // FROM: Sim TO: IRC | 225 | // FROM: Sim TO: IRC |
226 | 226 | ||
227 | ScenePresence avatar = null; | 227 | ScenePresence avatar = null; |
228 | 228 | ||
229 | //TODO: Move ForEachScenePresence and others into IScene. | 229 | //TODO: Move ForEachScenePresence and others into IScene. |
230 | Scene scene = (Scene) e.Scene; | 230 | Scene scene = (Scene) e.Scene; |
231 | 231 | ||
232 | //TODO: Remove the need for this check | 232 | //TODO: Remove the need for this check |
233 | if (scene == null) | 233 | if (scene == null) |
234 | scene = m_scenes[0]; | 234 | scene = m_scenes[0]; |
235 | 235 | ||
236 | // Filled in since it's easier than rewriting right now. | 236 | // Filled in since it's easier than rewriting right now. |
237 | LLVector3 fromPos = e.Position; | 237 | LLVector3 fromPos = e.Position; |
238 | LLVector3 regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); | 238 | LLVector3 regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); |
239 | 239 | ||
240 | string fromName = e.From; | 240 | string fromName = e.From; |
241 | string message = e.Message; | 241 | string message = e.Message; |
242 | LLUUID fromAgentID = LLUUID.Zero; | 242 | LLUUID fromAgentID = LLUUID.Zero; |
243 | 243 | ||
244 | if (e.Sender != null) | 244 | if (e.Sender != null) |
245 | { | 245 | { |
246 | avatar = scene.GetScenePresence(e.Sender.AgentId); | 246 | avatar = scene.GetScenePresence(e.Sender.AgentId); |
247 | } | 247 | } |
248 | 248 | ||
249 | if (avatar != null) | 249 | if (avatar != null) |
250 | { | 250 | { |
251 | fromPos = avatar.AbsolutePosition; | 251 | fromPos = avatar.AbsolutePosition; |
252 | regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); | 252 | regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); |
253 | fromName = avatar.Firstname + " " + avatar.Lastname; | 253 | fromName = avatar.Firstname + " " + avatar.Lastname; |
254 | fromAgentID = e.Sender.AgentId; | 254 | fromAgentID = e.Sender.AgentId; |
255 | } | 255 | } |
256 | 256 | ||
257 | // Try to reconnect to server if not connected | 257 | // Try to reconnect to server if not connected |
258 | if (m_irc.Enabled && !m_irc.Connected) | 258 | if (m_irc.Enabled && !m_irc.Connected) |
259 | { | 259 | { |
260 | // In a non-blocking way. Eventually the connector will get it started | 260 | // In a non-blocking way. Eventually the connector will get it started |
261 | try | 261 | try |
262 | { | 262 | { |
263 | if (m_irc_connector == null) | 263 | if (m_irc_connector == null) |
264 | { | 264 | { |
265 | m_irc_connector = new Thread(IRCConnectRun); | 265 | m_irc_connector = new Thread(IRCConnectRun); |
266 | m_irc_connector.Name = "IRCConnectorThread"; | 266 | m_irc_connector.Name = "IRCConnectorThread"; |
267 | m_irc_connector.IsBackground = true; | 267 | m_irc_connector.IsBackground = true; |
268 | } | 268 | } |
269 | if (!m_irc_connector.IsAlive) | 269 | if (!m_irc_connector.IsAlive) |
270 | { | 270 | { |
271 | m_irc_connector.Start(); | 271 | m_irc_connector.Start(); |
272 | ThreadTracker.Add(m_irc_connector); | 272 | ThreadTracker.Add(m_irc_connector); |
273 | } | 273 | } |
274 | } | 274 | } |
275 | catch (Exception) | 275 | catch (Exception) |
276 | { | 276 | { |
277 | } | 277 | } |
278 | } | 278 | } |
279 | 279 | ||
280 | 280 | ||
281 | // We only want to relay stuff on channel 0 | 281 | // We only want to relay stuff on channel 0 |
282 | if (e.Channel == 0) | 282 | if (e.Channel == 0) |
283 | { | 283 | { |
284 | // IRC stuff | 284 | // IRC stuff |
285 | if (e.Message.Length > 0) | 285 | if (e.Message.Length > 0) |
286 | { | 286 | { |
287 | if (m_irc.Connected && (avatar != null)) // this is to keep objects from talking to IRC | 287 | if (m_irc.Connected && (avatar != null)) // this is to keep objects from talking to IRC |
288 | { | 288 | { |
289 | m_irc.PrivMsg(fromName, scene.RegionInfo.RegionName, e.Message); | 289 | m_irc.PrivMsg(fromName, scene.RegionInfo.RegionName, e.Message); |
290 | } | 290 | } |
291 | } | 291 | } |
292 | 292 | ||
293 | foreach (Scene s in m_scenes) | 293 | foreach (Scene s in m_scenes) |
294 | { | 294 | { |
295 | s.ForEachScenePresence(delegate(ScenePresence presence) | 295 | s.ForEachScenePresence(delegate(ScenePresence presence) |
296 | { | 296 | { |
297 | TrySendChatMessage(presence, fromPos, regionPos, | 297 | TrySendChatMessage(presence, fromPos, regionPos, |
298 | fromAgentID, fromName, e.Type, message); | 298 | fromAgentID, fromName, e.Type, message); |
299 | }); | 299 | }); |
300 | } | 300 | } |
301 | } | 301 | } |
302 | } | 302 | } |
303 | 303 | ||
304 | // if IRC is enabled then just keep trying using a monitor thread | 304 | // if IRC is enabled then just keep trying using a monitor thread |
305 | public void IRCConnectRun() | 305 | public void IRCConnectRun() |
306 | { | 306 | { |
307 | while(true) | 307 | while(true) |
308 | { | 308 | { |
309 | if ((m_irc.Enabled)&&(!m_irc.Connected)) | 309 | if ((m_irc.Enabled)&&(!m_irc.Connected)) |
310 | { | 310 | { |
311 | m_irc.Connect(m_scenes); | 311 | m_irc.Connect(m_scenes); |
312 | } | 312 | } |
313 | Thread.Sleep(15000); | 313 | Thread.Sleep(15000); |
314 | } | 314 | } |
315 | } | 315 | } |
316 | 316 | ||
317 | public string FindClientRegion(string client_FirstName,string client_LastName) | 317 | public string FindClientRegion(string client_FirstName,string client_LastName) |
318 | { | 318 | { |
319 | string sourceRegion = null; | 319 | string sourceRegion = null; |
320 | foreach (Scene s in m_scenes) | 320 | foreach (Scene s in m_scenes) |
321 | { | 321 | { |
322 | s.ForEachScenePresence(delegate(ScenePresence presence) | 322 | s.ForEachScenePresence(delegate(ScenePresence presence) |
323 | { | 323 | { |
324 | if ((presence.IsChildAgent==false) | 324 | if ((presence.IsChildAgent==false) |
325 | &&(presence.Firstname==client_FirstName) | 325 | &&(presence.Firstname==client_FirstName) |
326 | &&(presence.Lastname==client_LastName)) | 326 | &&(presence.Lastname==client_LastName)) |
327 | { | 327 | { |
328 | sourceRegion = presence.Scene.RegionInfo.RegionName; | 328 | sourceRegion = presence.Scene.RegionInfo.RegionName; |
329 | //sourceRegion= s.RegionInfo.RegionName; | 329 | //sourceRegion= s.RegionInfo.RegionName; |
330 | } | 330 | } |
331 | }); | 331 | }); |
332 | if (sourceRegion != null) return sourceRegion; | 332 | if (sourceRegion != null) return sourceRegion; |
333 | } | 333 | } |
334 | if (m_defaultzone == null) { m_defaultzone = "Sim"; } | 334 | if (m_defaultzone == null) { m_defaultzone = "Sim"; } |
335 | return m_defaultzone; | 335 | return m_defaultzone; |
336 | } | 336 | } |
337 | } | 337 | } |
338 | 338 | ||
339 | internal class IRCChatModule | 339 | internal class IRCChatModule |
340 | { | 340 | { |
341 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 341 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
342 | 342 | ||
343 | private string m_server = null; | 343 | private string m_server = null; |
344 | private uint m_port = 6668; | 344 | private uint m_port = 6668; |
345 | private string m_user = "USER OpenSimBot 8 * :I'm a OpenSim to irc bot"; | 345 | private string m_user = "USER OpenSimBot 8 * :I'm a OpenSim to irc bot"; |
346 | private string m_nick = null; | 346 | private string m_nick = null; |
347 | private string m_basenick = null; | 347 | private string m_basenick = null; |
348 | private string m_channel = null; | 348 | private string m_channel = null; |
349 | private string m_privmsgformat = "PRIVMSG {0} :<{1} in {2}>: {3}"; | 349 | private string m_privmsgformat = "PRIVMSG {0} :<{1} in {2}>: {3}"; |
350 | 350 | ||
351 | private NetworkStream m_stream; | 351 | private NetworkStream m_stream; |
352 | private TcpClient m_tcp; | 352 | private TcpClient m_tcp; |
353 | private StreamWriter m_writer; | 353 | private StreamWriter m_writer; |
354 | private StreamReader m_reader; | 354 | private StreamReader m_reader; |
355 | 355 | ||
356 | private Thread pingSender; | 356 | private Thread pingSender; |
357 | private Thread listener; | 357 | private Thread listener; |
358 | internal object m_syncConnect = new object(); | 358 | internal object m_syncConnect = new object(); |
359 | 359 | ||
360 | private bool m_enabled = false; | 360 | private bool m_enabled = false; |
361 | private bool m_connected = false; | 361 | private bool m_connected = false; |
362 | 362 | ||
363 | private List<Scene> m_scenes = null; | 363 | private List<Scene> m_scenes = null; |
364 | private List<Scene> m_last_scenes = null; | 364 | private List<Scene> m_last_scenes = null; |
365 | 365 | ||
366 | public IRCChatModule(IConfigSource config) | 366 | public IRCChatModule(IConfigSource config) |
367 | { | 367 | { |
368 | m_nick = "OSimBot" + Util.RandomClass.Next(1, 99); | 368 | m_nick = "OSimBot" + Util.RandomClass.Next(1, 99); |
369 | m_tcp = null; | 369 | m_tcp = null; |
370 | m_writer = null; | 370 | m_writer = null; |
371 | m_reader = null; | 371 | m_reader = null; |
372 | 372 | ||
373 | // configuration in OpenSim.ini | 373 | // configuration in OpenSim.ini |
374 | // [IRC] | 374 | // [IRC] |
375 | // server = chat.freenode.net | 375 | // server = chat.freenode.net |
376 | // nick = OSimBot_mysim | 376 | // nick = OSimBot_mysim |
377 | // ;username = USER OpenSimBot 8 * :I'm a OpenSim to irc bot | 377 | // ;username = USER OpenSimBot 8 * :I'm a OpenSim to irc bot |
378 | // ; username is the IRC command line sent | 378 | // ; username is the IRC command line sent |
379 | // ; USER <irc_user> <visible=8,invisible=0> * : <IRC_realname> | 379 | // ; USER <irc_user> <visible=8,invisible=0> * : <IRC_realname> |
380 | // channel = #opensim-regions | 380 | // channel = #opensim-regions |
381 | // port = 6667 | 381 | // port = 6667 |
382 | // ;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message | 382 | // ;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message |
383 | // ;for <bot>:<user in region> :<message> | 383 | // ;for <bot>:<user in region> :<message> |
384 | // ;msgformat = "PRIVMSG {0} :<{1} in {2}>: {3}" | 384 | // ;msgformat = "PRIVMSG {0} :<{1} in {2}>: {3}" |
385 | // ;for <bot>:<message> - <user of region> : | 385 | // ;for <bot>:<message> - <user of region> : |
386 | // ;msgformat = "PRIVMSG {0} : {3} - {1} of {2}" | 386 | // ;msgformat = "PRIVMSG {0} : {3} - {1} of {2}" |
387 | // ;for <bot>:<message> - from <user> : | 387 | // ;for <bot>:<message> - from <user> : |
388 | // ;msgformat = "PRIVMSG {0} : {3} - from {1}" | 388 | // ;msgformat = "PRIVMSG {0} : {3} - from {1}" |
389 | // Traps I/O disconnects so it does not crash the sim | 389 | // Traps I/O disconnects so it does not crash the sim |
390 | // Trys to reconnect if disconnected and someone says something | 390 | // Trys to reconnect if disconnected and someone says something |
391 | // Tells IRC server "QUIT" when doing a close (just to be nice) | 391 | // Tells IRC server "QUIT" when doing a close (just to be nice) |
392 | // Default port back to 6667 | 392 | // Default port back to 6667 |
393 | 393 | ||
394 | try | 394 | try |
395 | { | 395 | { |
396 | m_server = config.Configs["IRC"].GetString("server"); | 396 | m_server = config.Configs["IRC"].GetString("server"); |
397 | m_nick = config.Configs["IRC"].GetString("nick"); | 397 | m_nick = config.Configs["IRC"].GetString("nick"); |
398 | m_basenick = m_nick; | 398 | m_basenick = m_nick; |
399 | m_channel = config.Configs["IRC"].GetString("channel"); | 399 | m_channel = config.Configs["IRC"].GetString("channel"); |
400 | m_port = (uint) config.Configs["IRC"].GetInt("port", (int) m_port); | 400 | m_port = (uint) config.Configs["IRC"].GetInt("port", (int) m_port); |
401 | m_user = config.Configs["IRC"].GetString("username", m_user); | 401 | m_user = config.Configs["IRC"].GetString("username", m_user); |
402 | m_privmsgformat = config.Configs["IRC"].GetString("msgformat", m_privmsgformat); | 402 | m_privmsgformat = config.Configs["IRC"].GetString("msgformat", m_privmsgformat); |
403 | if (m_server != null && m_nick != null && m_channel != null) | 403 | if (m_server != null && m_nick != null && m_channel != null) |
404 | { | 404 | { |
405 | m_nick = m_nick + Util.RandomClass.Next(1, 99); | 405 | m_nick = m_nick + Util.RandomClass.Next(1, 99); |
406 | m_enabled = true; | 406 | m_enabled = true; |
407 | } | 407 | } |
408 | } | 408 | } |
409 | catch (Exception) | 409 | catch (Exception) |
410 | { | 410 | { |
411 | m_log.Info("[CHAT]: No IRC config information, skipping IRC bridge configuration"); | 411 | m_log.Info("[CHAT]: No IRC config information, skipping IRC bridge configuration"); |
412 | } | 412 | } |
413 | } | 413 | } |
414 | 414 | ||
415 | public bool Connect(List<Scene> scenes) | 415 | public bool Connect(List<Scene> scenes) |
416 | { | 416 | { |
417 | lock (m_syncConnect) | 417 | lock (m_syncConnect) |
418 | { | 418 | { |
419 | try | 419 | try |
420 | { | 420 | { |
421 | if (m_connected) return true; | 421 | if (m_connected) return true; |
422 | m_scenes = scenes; | 422 | m_scenes = scenes; |
423 | if (m_last_scenes == null) { m_last_scenes = scenes; } | 423 | if (m_last_scenes == null) { m_last_scenes = scenes; } |
424 | 424 | ||
425 | m_tcp = new TcpClient(m_server, (int)m_port); | 425 | m_tcp = new TcpClient(m_server, (int)m_port); |
426 | m_log.Info("[IRC]: Connecting..."); | 426 | m_log.Info("[IRC]: Connecting..."); |
427 | m_stream = m_tcp.GetStream(); | 427 | m_stream = m_tcp.GetStream(); |
428 | m_log.Info("[IRC]: Connected to " + m_server); | 428 | m_log.Info("[IRC]: Connected to " + m_server); |
429 | m_reader = new StreamReader(m_stream); | 429 | m_reader = new StreamReader(m_stream); |
430 | m_writer = new StreamWriter(m_stream); | 430 | m_writer = new StreamWriter(m_stream); |
431 | 431 | ||
432 | pingSender = new Thread(new ThreadStart(PingRun)); | 432 | pingSender = new Thread(new ThreadStart(PingRun)); |
433 | pingSender.Name = "PingSenderThread"; | 433 | pingSender.Name = "PingSenderThread"; |
434 | pingSender.IsBackground = true; | 434 | pingSender.IsBackground = true; |
435 | pingSender.Start(); | 435 | pingSender.Start(); |
436 | ThreadTracker.Add(pingSender); | 436 | ThreadTracker.Add(pingSender); |
437 | 437 | ||
438 | listener = new Thread(new ThreadStart(ListenerRun)); | 438 | listener = new Thread(new ThreadStart(ListenerRun)); |
439 | listener.Name = "IRCChatModuleListenerThread"; | 439 | listener.Name = "IRCChatModuleListenerThread"; |
440 | listener.IsBackground = true; | 440 | listener.IsBackground = true; |
441 | listener.Start(); | 441 | listener.Start(); |
442 | ThreadTracker.Add(listener); | 442 | ThreadTracker.Add(listener); |
443 | 443 | ||
444 | m_writer.WriteLine(m_user); | 444 | m_writer.WriteLine(m_user); |
445 | m_writer.Flush(); | 445 | m_writer.Flush(); |
446 | m_writer.WriteLine("NICK " + m_nick); | 446 | m_writer.WriteLine("NICK " + m_nick); |
447 | m_writer.Flush(); | 447 | m_writer.Flush(); |
448 | m_writer.WriteLine("JOIN " + m_channel); | 448 | m_writer.WriteLine("JOIN " + m_channel); |
449 | m_writer.Flush(); | 449 | m_writer.Flush(); |
450 | m_log.Info("[IRC]: Connection fully established"); | 450 | m_log.Info("[IRC]: Connection fully established"); |
451 | m_connected = true; | 451 | m_connected = true; |
452 | } | 452 | } |
453 | catch (Exception e) | 453 | catch (Exception e) |
454 | { | 454 | { |
455 | Console.WriteLine(e.ToString()); | 455 | Console.WriteLine(e.ToString()); |
456 | } | 456 | } |
457 | return m_connected; | 457 | return m_connected; |
458 | } | 458 | } |
459 | } | 459 | } |
460 | 460 | ||
461 | public bool Enabled | 461 | public bool Enabled |
462 | { | 462 | { |
463 | get { return m_enabled; } | 463 | get { return m_enabled; } |
464 | } | 464 | } |
465 | 465 | ||
466 | public bool Connected | 466 | public bool Connected |
467 | { | 467 | { |
468 | get { return m_connected; } | 468 | get { return m_connected; } |
469 | } | 469 | } |
470 | 470 | ||
471 | public string Nick | 471 | public string Nick |
472 | { | 472 | { |
473 | get { return m_nick; } | 473 | get { return m_nick; } |
474 | } | 474 | } |
475 | 475 | ||
476 | public void Reconnect() | 476 | public void Reconnect() |
477 | { | 477 | { |
478 | m_connected = false; | 478 | m_connected = false; |
479 | listener.Abort(); | 479 | listener.Abort(); |
480 | pingSender.Abort(); | 480 | pingSender.Abort(); |
481 | m_writer.Close(); | 481 | m_writer.Close(); |
482 | m_reader.Close(); | 482 | m_reader.Close(); |
483 | m_tcp.Close(); | 483 | m_tcp.Close(); |
484 | if (m_enabled) { Connect(m_last_scenes); } | 484 | if (m_enabled) { Connect(m_last_scenes); } |
485 | } | 485 | } |
486 | 486 | ||
487 | public void PrivMsg(string from, string region, string msg) | 487 | public void PrivMsg(string from, string region, string msg) |
488 | { | 488 | { |
489 | // One message to the IRC server | 489 | // One message to the IRC server |
490 | 490 | ||
491 | try | 491 | try |
492 | { | 492 | { |
493 | if (m_privmsgformat == null) | 493 | if (m_privmsgformat == null) |
494 | { | 494 | { |
495 | m_writer.WriteLine("PRIVMSG {0} :<{1} in {2}>: {3}", m_channel, from, region, msg); | 495 | m_writer.WriteLine("PRIVMSG {0} :<{1} in {2}>: {3}", m_channel, from, region, msg); |
496 | } | 496 | } |
497 | else | 497 | else |
498 | { | 498 | { |
499 | m_writer.WriteLine(m_privmsgformat, m_channel, from, region, msg); | 499 | m_writer.WriteLine(m_privmsgformat, m_channel, from, region, msg); |
500 | } | 500 | } |
501 | m_writer.Flush(); | 501 | m_writer.Flush(); |
502 | m_log.Info("[IRC]: PrivMsg " + from + " in " + region + " :" + msg); | 502 | m_log.Info("[IRC]: PrivMsg " + from + " in " + region + " :" + msg); |
503 | } | 503 | } |
504 | catch (IOException) | 504 | catch (IOException) |
505 | { | 505 | { |
506 | m_log.Error("[IRC]: Disconnected from IRC server.(PrivMsg)"); | 506 | m_log.Error("[IRC]: Disconnected from IRC server.(PrivMsg)"); |
507 | Reconnect(); | 507 | Reconnect(); |
508 | } | 508 | } |
509 | catch (Exception ex) | 509 | catch (Exception ex) |
510 | { | 510 | { |
511 | m_log.Error("[IRC]: PrivMsg exception trap:" + ex.ToString()); | 511 | m_log.Error("[IRC]: PrivMsg exception trap:" + ex.ToString()); |
512 | } | 512 | } |
513 | } | 513 | } |
514 | 514 | ||
515 | private Dictionary<string, string> ExtractMsg(string input) | 515 | private Dictionary<string, string> ExtractMsg(string input) |
516 | { | 516 | { |
517 | //examines IRC commands and extracts any private messages | 517 | //examines IRC commands and extracts any private messages |
518 | // which will then be reboadcast in the Sim | 518 | // which will then be reboadcast in the Sim |
519 | 519 | ||
520 | m_log.Info("[IRC]: ExtractMsg: " + input); | 520 | m_log.Info("[IRC]: ExtractMsg: " + input); |
521 | Dictionary<string, string> result = null; | 521 | Dictionary<string, string> result = null; |
522 | //string regex = @":(?<nick>\w*)!~(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)"; | 522 | //string regex = @":(?<nick>\w*)!~(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)"; |
523 | string regex = @":(?<nick>\w*)!(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)"; | 523 | string regex = @":(?<nick>\w*)!(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)"; |
524 | Regex RE = new Regex(regex, RegexOptions.Multiline); | 524 | Regex RE = new Regex(regex, RegexOptions.Multiline); |
525 | MatchCollection matches = RE.Matches(input); | 525 | MatchCollection matches = RE.Matches(input); |
526 | // Get some direct matches $1 $4 is a | 526 | // Get some direct matches $1 $4 is a |
527 | if ((matches.Count == 1) && (matches[0].Groups.Count == 5)) | 527 | if ((matches.Count == 1) && (matches[0].Groups.Count == 5)) |
528 | { | 528 | { |
529 | result = new Dictionary<string, string>(); | 529 | result = new Dictionary<string, string>(); |
530 | result.Add("nick", matches[0].Groups[1].Value); | 530 | result.Add("nick", matches[0].Groups[1].Value); |
531 | result.Add("user", matches[0].Groups[2].Value); | 531 | result.Add("user", matches[0].Groups[2].Value); |
532 | result.Add("channel", matches[0].Groups[3].Value); | 532 | result.Add("channel", matches[0].Groups[3].Value); |
533 | result.Add("msg", matches[0].Groups[4].Value); | 533 | result.Add("msg", matches[0].Groups[4].Value); |
534 | } | 534 | } |
535 | else | 535 | else |
536 | { | 536 | { |
537 | m_log.Info("[IRC]: Number of matches: " + matches.Count); | 537 | m_log.Info("[IRC]: Number of matches: " + matches.Count); |
538 | if (matches.Count > 0) | 538 | if (matches.Count > 0) |
539 | { | 539 | { |
540 | m_log.Info("[IRC]: Number of groups: " + matches[0].Groups.Count); | 540 | m_log.Info("[IRC]: Number of groups: " + matches[0].Groups.Count); |
541 | } | 541 | } |
542 | } | 542 | } |
543 | return result; | 543 | return result; |
544 | } | 544 | } |
545 | 545 | ||
546 | public void PingRun() | 546 | public void PingRun() |
547 | { | 547 | { |
548 | // IRC keep alive thread | 548 | // IRC keep alive thread |
549 | // send PING ever 15 seconds | 549 | // send PING ever 15 seconds |
550 | while (true) | 550 | while (true) |
551 | { | 551 | { |
552 | try | 552 | try |
553 | { | 553 | { |
554 | if (m_connected == true) | 554 | if (m_connected == true) |
555 | { | 555 | { |
556 | m_writer.WriteLine("PING :" + m_server); | 556 | m_writer.WriteLine("PING :" + m_server); |
557 | m_writer.Flush(); | 557 | m_writer.Flush(); |
558 | Thread.Sleep(15000); | 558 | Thread.Sleep(15000); |
559 | } | 559 | } |
560 | } | 560 | } |
561 | catch (IOException) | 561 | catch (IOException) |
562 | { | 562 | { |
563 | m_log.Error("[IRC]: Disconnected from IRC server.(PingRun)"); | 563 | m_log.Error("[IRC]: Disconnected from IRC server.(PingRun)"); |
564 | Reconnect(); | 564 | Reconnect(); |
565 | } | 565 | } |
566 | catch (Exception ex) | 566 | catch (Exception ex) |
567 | { | 567 | { |
568 | m_log.Error("[IRC]: PingRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace); | 568 | m_log.Error("[IRC]: PingRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace); |
569 | } | 569 | } |
570 | } | 570 | } |
571 | } | 571 | } |
572 | 572 | ||
573 | public void ListenerRun() | 573 | public void ListenerRun() |
574 | { | 574 | { |
575 | string inputLine; | 575 | string inputLine; |
576 | LLVector3 pos = new LLVector3(128, 128, 20); | 576 | LLVector3 pos = new LLVector3(128, 128, 20); |
577 | while (true) | 577 | while (true) |
578 | { | 578 | { |
579 | try | 579 | try |
580 | { | 580 | { |
581 | while ((m_connected == true) && ((inputLine = m_reader.ReadLine()) != null)) | 581 | while ((m_connected == true) && ((inputLine = m_reader.ReadLine()) != null)) |
582 | { | 582 | { |
583 | // Console.WriteLine(inputLine); | 583 | // Console.WriteLine(inputLine); |
584 | if (inputLine.Contains(m_channel)) | 584 | if (inputLine.Contains(m_channel)) |
585 | { | 585 | { |
586 | Dictionary<string, string> data = ExtractMsg(inputLine); | 586 | Dictionary<string, string> data = ExtractMsg(inputLine); |
587 | // Any chat ??? | 587 | // Any chat ??? |
588 | if (data != null) | 588 | if (data != null) |
589 | { | 589 | { |
590 | foreach (Scene m_scene in m_scenes) | 590 | foreach (Scene m_scene in m_scenes) |
591 | { | 591 | { |
592 | m_scene.ForEachScenePresence(delegate(ScenePresence avatar) | 592 | m_scene.ForEachScenePresence(delegate(ScenePresence avatar) |
593 | { | 593 | { |
594 | if (!avatar.IsChildAgent) | 594 | if (!avatar.IsChildAgent) |
595 | { | 595 | { |
596 | avatar.ControllingClient.SendChatMessage( | 596 | avatar.ControllingClient.SendChatMessage( |
597 | Helpers.StringToField(data["msg"]), 255, | 597 | Helpers.StringToField(data["msg"]), 255, |
598 | pos, data["nick"], | 598 | pos, data["nick"], |
599 | LLUUID.Zero); | 599 | LLUUID.Zero); |
600 | } | 600 | } |
601 | }); | 601 | }); |
602 | } | 602 | } |
603 | } | 603 | } |
604 | else | 604 | else |
605 | { | 605 | { |
606 | // Was an command from the IRC server | 606 | // Was an command from the IRC server |
607 | ProcessIRCCommand(inputLine); | 607 | ProcessIRCCommand(inputLine); |
608 | } | 608 | } |
609 | } | 609 | } |
610 | else | 610 | else |
611 | { | 611 | { |
612 | // Was an command from the IRC server | 612 | // Was an command from the IRC server |
613 | ProcessIRCCommand(inputLine); | 613 | ProcessIRCCommand(inputLine); |
614 | } | 614 | } |
615 | Thread.Sleep(150); | 615 | Thread.Sleep(150); |
616 | } | 616 | } |
617 | } | 617 | } |
618 | catch (IOException) | 618 | catch (IOException) |
619 | { | 619 | { |
620 | m_log.Error("[IRC]: ListenerRun IOException. Disconnected from IRC server ??? (ListenerRun)"); | 620 | m_log.Error("[IRC]: ListenerRun IOException. Disconnected from IRC server ??? (ListenerRun)"); |
621 | Reconnect(); | 621 | Reconnect(); |
622 | } | 622 | } |
623 | catch (Exception ex) | 623 | catch (Exception ex) |
624 | { | 624 | { |
625 | m_log.Error("[IRC]: ListenerRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace); | 625 | m_log.Error("[IRC]: ListenerRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace); |
626 | } | 626 | } |
627 | } | 627 | } |
628 | } | 628 | } |
629 | 629 | ||
630 | public void BroadcastSim(string message,string sender) | 630 | public void BroadcastSim(string message,string sender) |
631 | { | 631 | { |
632 | LLVector3 pos = new LLVector3(128, 128, 20); | 632 | LLVector3 pos = new LLVector3(128, 128, 20); |
633 | try | 633 | try |
634 | { | 634 | { |
635 | foreach (Scene m_scene in m_scenes) | 635 | foreach (Scene m_scene in m_scenes) |
636 | { | 636 | { |
637 | m_scene.ForEachScenePresence(delegate(ScenePresence avatar) | 637 | m_scene.ForEachScenePresence(delegate(ScenePresence avatar) |
638 | { | 638 | { |
639 | if (!avatar.IsChildAgent) | 639 | if (!avatar.IsChildAgent) |
640 | { | 640 | { |
641 | avatar.ControllingClient.SendChatMessage( | 641 | avatar.ControllingClient.SendChatMessage( |
642 | Helpers.StringToField(message), 255, | 642 | Helpers.StringToField(message), 255, |
643 | pos, sender, | 643 | pos, sender, |
644 | LLUUID.Zero); | 644 | LLUUID.Zero); |
645 | } | 645 | } |
646 | }); | 646 | }); |
647 | } | 647 | } |
648 | } | 648 | } |
649 | catch (Exception ex) // IRC gate should not crash Sim | 649 | catch (Exception ex) // IRC gate should not crash Sim |
650 | { | 650 | { |
651 | m_log.Error("[IRC]: BroadcastSim Exception Trap:" + ex.ToString() + "\n" + ex.StackTrace); | 651 | m_log.Error("[IRC]: BroadcastSim Exception Trap:" + ex.ToString() + "\n" + ex.StackTrace); |
652 | } | 652 | } |
653 | } | 653 | } |
654 | 654 | ||
655 | public enum ErrorReplies | 655 | public enum ErrorReplies |
656 | { | 656 | { |
657 | NotRegistered = 451, // ":You have not registered" | 657 | NotRegistered = 451, // ":You have not registered" |
658 | NicknameInUse = 433 // "<nick> :Nickname is already in use" | 658 | NicknameInUse = 433 // "<nick> :Nickname is already in use" |
659 | } | 659 | } |
660 | 660 | ||
661 | public enum Replies | 661 | public enum Replies |
662 | { | 662 | { |
663 | MotdStart = 375, // ":- <server> Message of the day - " | 663 | MotdStart = 375, // ":- <server> Message of the day - " |
664 | Motd = 372, // ":- <text>" | 664 | Motd = 372, // ":- <text>" |
665 | EndOfMotd = 376 // ":End of /MOTD command" | 665 | EndOfMotd = 376 // ":End of /MOTD command" |
666 | } | 666 | } |
667 | 667 | ||
668 | public void ProcessIRCCommand(string command) | 668 | public void ProcessIRCCommand(string command) |
669 | { | 669 | { |
670 | //m_log.Info("[IRC]: ProcessIRCCommand:" + command); | 670 | //m_log.Info("[IRC]: ProcessIRCCommand:" + command); |
671 | 671 | ||
672 | string[] commArgs = new string[command.Split(' ').Length]; | 672 | string[] commArgs = new string[command.Split(' ').Length]; |
673 | string c_server = m_server; | 673 | string c_server = m_server; |
674 | 674 | ||
675 | commArgs = command.Split(' '); | 675 | commArgs = command.Split(' '); |
676 | if (commArgs[0].Substring(0, 1) == ":") | 676 | if (commArgs[0].Substring(0, 1) == ":") |
677 | { | 677 | { |
678 | commArgs[0] = commArgs[0].Remove(0, 1); | 678 | commArgs[0] = commArgs[0].Remove(0, 1); |
679 | } | 679 | } |
680 | 680 | ||
681 | if (commArgs[1] == "002") | 681 | if (commArgs[1] == "002") |
682 | { | 682 | { |
683 | // fetch the correct servername | 683 | // fetch the correct servername |
684 | // ex: irc.freenode.net -> brown.freenode.net/kornbluth.freenode.net/... | 684 | // ex: irc.freenode.net -> brown.freenode.net/kornbluth.freenode.net/... |
685 | // irc.bluewin.ch -> irc1.bluewin.ch/irc2.bluewin.ch | 685 | // irc.bluewin.ch -> irc1.bluewin.ch/irc2.bluewin.ch |
686 | 686 | ||
687 | c_server = (commArgs[6].Split('['))[0]; | 687 | c_server = (commArgs[6].Split('['))[0]; |
688 | m_server = c_server; | 688 | m_server = c_server; |
689 | } | 689 | } |
690 | 690 | ||
691 | if (commArgs[0] == "ERROR") | 691 | if (commArgs[0] == "ERROR") |
692 | { | 692 | { |
693 | m_log.Error("[IRC]: IRC SERVER ERROR:" + command); | 693 | m_log.Error("[IRC]: IRC SERVER ERROR:" + command); |
694 | } | 694 | } |
695 | 695 | ||
696 | if (commArgs[0] == "PING") | 696 | if (commArgs[0] == "PING") |
697 | { | 697 | { |
698 | string p_reply = ""; | 698 | string p_reply = ""; |
699 | 699 | ||
700 | for (int i = 1; i < commArgs.Length; i++) | 700 | for (int i = 1; i < commArgs.Length; i++) |
701 | { | 701 | { |
702 | p_reply += commArgs[i] + " "; | 702 | p_reply += commArgs[i] + " "; |
703 | } | 703 | } |
704 | 704 | ||
705 | m_writer.WriteLine("PONG " + p_reply); | 705 | m_writer.WriteLine("PONG " + p_reply); |
706 | m_writer.Flush(); | 706 | m_writer.Flush(); |
707 | } | 707 | } |
708 | else if (commArgs[0] == c_server) | 708 | else if (commArgs[0] == c_server) |
709 | { | 709 | { |
710 | // server message | 710 | // server message |
711 | try | 711 | try |
712 | { | 712 | { |
713 | Int32 commandCode = Int32.Parse(commArgs[1]); | 713 | Int32 commandCode = Int32.Parse(commArgs[1]); |
714 | switch (commandCode) | 714 | switch (commandCode) |
715 | { | 715 | { |
716 | case (int)ErrorReplies.NicknameInUse: | 716 | case (int)ErrorReplies.NicknameInUse: |
717 | // Gen a new name | 717 | // Gen a new name |
718 | m_nick = m_basenick + Util.RandomClass.Next(1, 99); | 718 | m_nick = m_basenick + Util.RandomClass.Next(1, 99); |
719 | m_log.Error("[IRC]: IRC SERVER reports NicknameInUse, trying " + m_nick); | 719 | m_log.Error("[IRC]: IRC SERVER reports NicknameInUse, trying " + m_nick); |
720 | // Retry | 720 | // Retry |
721 | m_writer.WriteLine("NICK " + m_nick); | 721 | m_writer.WriteLine("NICK " + m_nick); |
722 | m_writer.Flush(); | 722 | m_writer.Flush(); |
723 | m_writer.WriteLine("JOIN " + m_channel); | 723 | m_writer.WriteLine("JOIN " + m_channel); |
724 | m_writer.Flush(); | 724 | m_writer.Flush(); |
725 | break; | 725 | break; |
726 | case (int)ErrorReplies.NotRegistered: | 726 | case (int)ErrorReplies.NotRegistered: |
727 | break; | 727 | break; |
728 | case (int)Replies.EndOfMotd: | 728 | case (int)Replies.EndOfMotd: |
729 | break; | 729 | break; |
730 | } | 730 | } |
731 | } | 731 | } |
732 | catch (Exception) | 732 | catch (Exception) |
733 | { | 733 | { |
734 | } | 734 | } |
735 | } | 735 | } |
736 | else | 736 | else |
737 | { | 737 | { |
738 | // Normal message | 738 | // Normal message |
739 | string commAct = commArgs[1]; | 739 | string commAct = commArgs[1]; |
740 | switch (commAct) | 740 | switch (commAct) |
741 | { | 741 | { |
742 | case "JOIN": eventIrcJoin(commArgs); break; | 742 | case "JOIN": eventIrcJoin(commArgs); break; |
743 | case "PART": eventIrcPart(commArgs); break; | 743 | case "PART": eventIrcPart(commArgs); break; |
744 | case "MODE": eventIrcMode(commArgs); break; | 744 | case "MODE": eventIrcMode(commArgs); break; |
745 | case "NICK": eventIrcNickChange(commArgs); break; | 745 | case "NICK": eventIrcNickChange(commArgs); break; |
746 | case "KICK": eventIrcKick(commArgs); break; | 746 | case "KICK": eventIrcKick(commArgs); break; |
747 | case "QUIT": eventIrcQuit(commArgs); break; | 747 | case "QUIT": eventIrcQuit(commArgs); break; |
748 | case "PONG": break; // that's nice | 748 | case "PONG": break; // that's nice |
749 | } | 749 | } |
750 | } | 750 | } |
751 | } | 751 | } |
752 | 752 | ||
753 | public void eventIrcJoin(string[] commArgs) | 753 | public void eventIrcJoin(string[] commArgs) |
754 | { | 754 | { |
755 | string IrcChannel = commArgs[2]; | 755 | string IrcChannel = commArgs[2]; |
756 | string IrcUser = commArgs[0].Split('!')[0]; | 756 | string IrcUser = commArgs[0].Split('!')[0]; |
757 | BroadcastSim(IrcUser + " is joining " + IrcChannel, m_nick); | 757 | BroadcastSim(IrcUser + " is joining " + IrcChannel, m_nick); |
758 | } | 758 | } |
759 | 759 | ||
760 | public void eventIrcPart(string[] commArgs) | 760 | public void eventIrcPart(string[] commArgs) |
761 | { | 761 | { |
762 | string IrcChannel = commArgs[2]; | 762 | string IrcChannel = commArgs[2]; |
763 | string IrcUser = commArgs[0].Split('!')[0]; | 763 | string IrcUser = commArgs[0].Split('!')[0]; |
764 | BroadcastSim(IrcUser + " is parting " + IrcChannel, m_nick); | 764 | BroadcastSim(IrcUser + " is parting " + IrcChannel, m_nick); |
765 | } | 765 | } |
766 | 766 | ||
767 | public void eventIrcMode(string[] commArgs) | 767 | public void eventIrcMode(string[] commArgs) |
768 | { | 768 | { |
769 | string IrcChannel = commArgs[2]; | 769 | string IrcChannel = commArgs[2]; |
770 | string IrcUser = commArgs[0].Split('!')[0]; | 770 | string IrcUser = commArgs[0].Split('!')[0]; |
771 | string UserMode = ""; | 771 | string UserMode = ""; |
772 | for (int i = 3; i < commArgs.Length; i++) | 772 | for (int i = 3; i < commArgs.Length; i++) |
773 | { | 773 | { |
774 | UserMode += commArgs[i] + " "; | 774 | UserMode += commArgs[i] + " "; |
775 | } | 775 | } |
776 | 776 | ||
777 | if (UserMode.Substring(0, 1) == ":") | 777 | if (UserMode.Substring(0, 1) == ":") |
778 | { | 778 | { |
779 | UserMode = UserMode.Remove(0, 1); | 779 | UserMode = UserMode.Remove(0, 1); |
780 | } | 780 | } |
781 | } | 781 | } |
782 | 782 | ||
783 | public void eventIrcNickChange(string[] commArgs) | 783 | public void eventIrcNickChange(string[] commArgs) |
784 | { | 784 | { |
785 | string UserOldNick = commArgs[0].Split('!')[0]; | 785 | string UserOldNick = commArgs[0].Split('!')[0]; |
786 | string UserNewNick = commArgs[2].Remove(0, 1); | 786 | string UserNewNick = commArgs[2].Remove(0, 1); |
787 | BroadcastSim(UserOldNick + " changed their nick to " + UserNewNick, m_nick); | 787 | BroadcastSim(UserOldNick + " changed their nick to " + UserNewNick, m_nick); |
788 | } | 788 | } |
789 | 789 | ||
790 | public void eventIrcKick(string[] commArgs) | 790 | public void eventIrcKick(string[] commArgs) |
791 | { | 791 | { |
792 | string UserKicker = commArgs[0].Split('!')[0]; | 792 | string UserKicker = commArgs[0].Split('!')[0]; |
793 | string UserKicked = commArgs[3]; | 793 | string UserKicked = commArgs[3]; |
794 | string IrcChannel = commArgs[2]; | 794 | string IrcChannel = commArgs[2]; |
795 | string KickMessage = ""; | 795 | string KickMessage = ""; |
796 | for (int i = 4; i < commArgs.Length; i++) | 796 | for (int i = 4; i < commArgs.Length; i++) |
797 | { | 797 | { |
798 | KickMessage += commArgs[i] + " "; | 798 | KickMessage += commArgs[i] + " "; |
799 | } | 799 | } |
800 | BroadcastSim(UserKicker + " kicked " + UserKicked +" on "+IrcChannel+" saying "+KickMessage, m_nick); | 800 | BroadcastSim(UserKicker + " kicked " + UserKicked +" on "+IrcChannel+" saying "+KickMessage, m_nick); |
801 | if (UserKicked == m_nick) | 801 | if (UserKicked == m_nick) |
802 | { | 802 | { |
803 | BroadcastSim("Hey, that was me!!!", m_nick); | 803 | BroadcastSim("Hey, that was me!!!", m_nick); |
804 | } | 804 | } |
805 | } | 805 | } |
806 | 806 | ||
807 | public void eventIrcQuit(string[] commArgs) | 807 | public void eventIrcQuit(string[] commArgs) |
808 | { | 808 | { |
809 | string IrcUser = commArgs[0].Split('!')[0]; | 809 | string IrcUser = commArgs[0].Split('!')[0]; |
810 | string QuitMessage = ""; | 810 | string QuitMessage = ""; |
811 | 811 | ||
812 | for (int i = 2; i < commArgs.Length; i++) | 812 | for (int i = 2; i < commArgs.Length; i++) |
813 | { | 813 | { |
814 | QuitMessage += commArgs[i] + " "; | 814 | QuitMessage += commArgs[i] + " "; |
815 | } | 815 | } |
816 | BroadcastSim(IrcUser + " quits saying " + QuitMessage, m_nick); | 816 | BroadcastSim(IrcUser + " quits saying " + QuitMessage, m_nick); |
817 | } | 817 | } |
818 | 818 | ||
819 | public void Close() | 819 | public void Close() |
820 | { | 820 | { |
821 | m_connected = false; | 821 | m_connected = false; |
822 | m_writer.WriteLine("QUIT :" + m_nick + " to " + m_channel + " wormhole with " + m_server + " closing"); | 822 | m_writer.WriteLine("QUIT :" + m_nick + " to " + m_channel + " wormhole with " + m_server + " closing"); |
823 | m_writer.Flush(); | 823 | m_writer.Flush(); |
824 | listener.Abort(); | 824 | listener.Abort(); |
825 | pingSender.Abort(); | 825 | pingSender.Abort(); |
826 | m_writer.Close(); | 826 | m_writer.Close(); |
827 | m_reader.Close(); | 827 | m_reader.Close(); |
828 | m_tcp.Close(); | 828 | m_tcp.Close(); |
829 | } | 829 | } |
830 | } | 830 | } |
831 | } | 831 | } \ No newline at end of file |