/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2012 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// using System; using System.Text; using System.Text.RegularExpressions; using System.IO; using System.Threading; using System.Collections.Generic; using OpenMetaverse; using System.Linq; namespace Claviger { internal class Claviger { private static readonly GridClient Client = new GridClient(); private static string _firstName = string.Empty; private static string _lastName = string.Empty; private static string _password = string.Empty; private static List < UUID > _masters = new List < UUID > (); private static readonly Thread MainConnectionThread = new Thread(MainConnection); private static Dictionary < char, bool > StabilizeChecks = new Dictionary < char, bool > () { { 'l', false }, { 'e', false }, { 's', false }, { 'a', false } }; private static List < string > AuthAgents = new List < string > (); private static UUID _sitTargetUUID; private static volatile bool _run = true; public static void Main() { Settings.LOG_LEVEL = Helpers.LogLevel.None; Client.Settings.STORE_LAND_PATCHES = true; Client.Settings.ALWAYS_DECODE_OBJECTS = true; Client.Settings.ALWAYS_REQUEST_OBJECTS = true; Client.Settings.SEND_AGENT_UPDATES = true; Client.Settings.USE_ASSET_CACHE = false; Client.Settings.FETCH_MISSING_INVENTORY = true; Client.Network.LoginProgress += HandleLoginProgress; Client.Appearance.AppearanceSet += HandleAppearanceSet; Client.Network.SimConnected += HandleSimulatorConnected; Client.Network.Disconnected += HandleDisconnected; Client.Network.SimDisconnected += HandleSimulatorDisconnected; Client.Network.EventQueueRunning += HandleEventQueueRunning; Client.Friends.FriendshipOffered += HandleFriendshipOffered; Client.Self.ScriptQuestion += HandleScriptQuestion; Client.Self.IM += HandleSelfIM; try { foreach(string cfg in File.ReadLines("Claviger.config")) { string[] data = cfg.Split(new char[] { ':' }, 2); switch (data[0]) { case "firstname": _firstName = data[1]; break; case "lastname": _lastName = data[1]; break; case "password": _password = data[1]; break; case "grid": Client.Settings.LOGIN_SERVER = data[1]; break; // auth-secrets and masters are read dynamically on request. case "master": break; case "secret": break; default: Console.WriteLine("[Claviger] : Garbled line: " + cfg + ", the program will now terminate."); System.Environment.Exit(1); break; } } } catch (FileNotFoundException) { Console.WriteLine("[Claviger] : Could not read configuration file."); System.Environment.Exit(1); } new List < int > (new int[Console.WindowWidth]).ForEach(i => Console.Write("-")); MainConnectionThread.Start(); } private static void HandleDisconnected(object sender, DisconnectedEventArgs e) { Console.Write("\n[Claviger] : Disconnected..."); if (!StabilizeChecks.ContainsKey('l')) { StabilizeChecks.Add('l', false); return; } StabilizeChecks['l'] = false; } private static void HandleEventQueueRunning(object sender, EventQueueRunningEventArgs e) { Console.Write("\n[Claviger] : Event queue started..."); if (!StabilizeChecks.ContainsKey('e')) { StabilizeChecks.Add('e', true); return; } StabilizeChecks['e'] = true; } private static void HandleSimulatorConnected(object sender, SimConnectedEventArgs e) { Console.Write("\n[Claviger] : Simulator connected..."); if (!StabilizeChecks.ContainsKey('s')) { StabilizeChecks.Add('s', true); return; } StabilizeChecks['s'] = true; } private static void HandleSimulatorDisconnected(object sender, SimDisconnectedEventArgs e) { if (Client.Network.Simulators.Count >= 1) return; Console.Write("\n[Claviger] : Simulators disconnected..."); if (!StabilizeChecks.ContainsKey('s')) { StabilizeChecks.Add('s', false); return; } StabilizeChecks['s'] = false; } private static void HandleAppearanceSet(object sender, AppearanceSetEventArgs e) { if (e.Success) { Console.Write("\n[Claviger] : Appearance set..."); if (!StabilizeChecks.ContainsKey('a')) { StabilizeChecks.Add('a', true); return; } StabilizeChecks['a'] = true; return; } Console.Write("\n[Claviger] : Failed to set appearance..."); if (!StabilizeChecks.ContainsKey('a')) { StabilizeChecks.Add('a', false); return; } StabilizeChecks['a'] = false; } private static void HandleLoginProgress(object sender, LoginProgressEventArgs e) { switch (e.Status) { case LoginStatus.Success: Console.Write("\n[Claviger] : Login ok..."); StabilizeChecks['l'] = true; break; case LoginStatus.Failed: Console.Write("\n[Claviger] : Failed Login..."); if (!StabilizeChecks.ContainsKey('l')) { StabilizeChecks.Add('l', false); break; } StabilizeChecks['l'] = false; break; } } private static void HandleFriendshipOffered(object sender, FriendshipOfferedEventArgs e) { if (!_masters.Contains(e.AgentID)) return; Console.Write("\n[Claviger] : Accepting friendship with " + e.AgentName + "."); Client.Friends.AcceptFriendship(e.AgentID, e.SessionID); } private static void MainConnection() { StabilizeChecks = new Dictionary < char, bool > (); Client.Network.BeginLogin(new LoginParams(Client, _firstName, _lastName, _password, "[WaS] Corrade", "1.0")); Console.Write("\n[Corrade] : Stabilizing, please wait..."); do { Console.Write("."); Thread.Sleep(1000); } while (StabilizeChecks.Count != 4 && !StabilizeChecks.ContainsValue(false)); if (!StabilizeChecks.ContainsValue(false)) Console.Write("\n[Corrade] : Fully connected and accepting commands."); do { Thread.Sleep(1000); if (StabilizeChecks.ContainsValue(false)) { Console.Write("\n[Corrade] : Disconnected, shutting down..."); _run = false; } } while (_run); Console.Write("\n[Corrade] : All operations completed. Quitting."); new List < int > (new int[Console.WindowWidth]).ForEach(i => Console.Write("-")); Client.Network.Logout(); Client.Network.Shutdown(NetworkManager.DisconnectType.ClientInitiated); } private static void HandleSelfIM(object sender, InstantMessageEventArgs e) { if (e.IM.Dialog.Equals(InstantMessageDialog.MessageBox)) { Console.Write("\n[Claviger] : [Server Message] : " + e.IM.Message.Replace(System.Environment.NewLine, " ")); return; } if (e.IM.Dialog.Equals(InstantMessageDialog.RequestTeleport)) { try { foreach(string cfg in File.ReadLines("Claviger.config")) { string[] data = cfg.Split(new char[] { ':' }, 3); switch (data[0]) { case "master": var master = UUID.Zero; if (!UUID.TryParse(data[1], out master)) continue; if (_masters.Contains(master)) continue; _masters.Add(master); break; } } } catch (FileNotFoundException) { Console.Write("\n[Claviger] : Could not read configuration file."); System.Environment.Exit(1); } if (!_masters.Contains(e.IM.FromAgentID)) return; Console.Write("\n[Claviger] : Accepting teleport lure."); Client.Self.TeleportLureRespond(e.IM.FromAgentID, e.IM.IMSessionID, true); return; } // Ignore group chat. if (e.IM.GroupIM) return; var msg = e.IM.Message.Split(new char[] { ' ' }); if (!msg[0].Equals("auth")) goto NoAuth; try { foreach(string cfg in File.ReadLines("Claviger.config")) { string[] data = cfg.Split(new char[] { ':' }, 3); switch (data[0]) { case "secret": if (!data[1].Equals(msg[1])) break; if (!AuthAgents.Contains(e.IM.FromAgentName)) AuthAgents.Add(e.IM.FromAgentName); Console.Write("\n[Claviger] : Authenticated: " + e.IM.FromAgentName + "."); break; } } } catch (FileNotFoundException) { Console.Write("\n[Claviger] : Could not read configuration file."); System.Environment.Exit(1); } return; NoAuth: if(!AuthAgents.Contains(e.IM.FromAgentName)) return; if (msg[0].Equals("s")) goto SitCommand; return; SitCommand: if (!UUID.TryParse(msg[1], out _sitTargetUUID)) return; Primitive targetPrim = Client.Network.CurrentSim.ObjectsPrimitives.Find( delegate(Primitive prim) { return prim.ID == _sitTargetUUID; }); if (targetPrim == null) return; Console.Write("\n[Claviger] : Sitting on: " + targetPrim.ID.ToString() + "."); Client.Self.RequestSit(targetPrim.ID, Vector3.Zero); Client.Self.Sit(); } private static void HandleScriptQuestion(object sender, ScriptQuestionEventArgs e) { if (e.ItemID != _sitTargetUUID) return; Client.Self.ScriptQuestionReply(Client.Network.CurrentSim, e.ItemID, e.TaskID, ScriptPermission.TriggerAnimation); } } }