Esempio n. 1
0
 /// <summary>
 /// Sets the plugin to an error state.
 /// </summary>
 /// <param name="e">The exception causing the error state.</param>
 internal void SetFailState(Exception e)
 {
     this.LoadStatus = Status.Error;
     this.Error      = e.Message;
     this.Plugin     = null;
     SMLog.Error(e, this.File);
 }
Esempio n. 2
0
 /// <summary>
 /// Raises the <see cref="ValueChanged"/> event.
 /// </summary>
 /// <param name="oldVal">The old value as a string.</param>
 /// <param name="newVal">The new value as a string.</param>
 internal void OnConVarChanged(string oldVal, string newVal)
 {
     if (this.ValueChanged != null)
     {
         var args = new ConVarChangedEventArgs(this, oldVal, newVal);
         foreach (EventHandler <ConVarChangedEventArgs> d in this.ValueChanged.GetInvocationList())
         {
             try
             {
                 d.Invoke(this, args);
             }
             catch (HaltPluginException)
             {
             }
             catch (Exception e)
             {
                 if (d.Target is IPlugin p)
                 {
                     p.Container.SetFailState(e);
                 }
                 else
                 {
                     SMLog.Error(e);
                 }
             }
         }
     }
 }
Esempio n. 3
0
        /// <summary>
        /// Checks the status of this query and publishes the result if it has completed.
        /// </summary>
        /// <returns><c>true</c> if this query has completed; otherwise <c>false</c>.</returns>
        internal bool CheckStatus()
        {
            if (this.status == Status.Completed)
            {
                if (this.QueryCompleted != null)
                {
                    var args = new QueryCompletedEventArgs(this.database, this.affectedRows, this.results, this.data, this.exception);
                    foreach (EventHandler <QueryCompletedEventArgs> d in this.QueryCompleted.GetInvocationList())
                    {
                        try
                        {
                            d.Invoke(this, args);
                        }
                        catch (HaltPluginException)
                        {
                        }
                        catch (Exception e)
                        {
                            if (d.Target is IPlugin p)
                            {
                                p.Container.SetFailState(e);
                            }
                            else
                            {
                                SMLog.Error(e);
                            }
                        }
                    }
                }

                this.status = Status.Published;
            }

            return(this.status == Status.Published);
        }
Esempio n. 4
0
 /// <summary>
 /// Raises the <see cref="Cancelled"/> event.
 /// </summary>
 private void OnVoteCancelled()
 {
     if (this.Cancelled != null)
     {
         foreach (EventHandler d in this.Cancelled.GetInvocationList())
         {
             try
             {
                 d.Invoke(this, EventArgs.Empty);
             }
             catch (HaltPluginException)
             {
             }
             catch (Exception e)
             {
                 if (d.Target is IPlugin p)
                 {
                     p.Container.SetFailState(e);
                 }
                 else
                 {
                     SMLog.Error(e);
                 }
             }
         }
     }
 }
Esempio n. 5
0
 /// <summary>
 /// Sets the plugin to an error state.
 /// </summary>
 /// <param name="error">The error message.</param>
 public void SetFailState(string error)
 {
     this.LoadStatus = Status.Error;
     this.Error      = error;
     this.Plugin     = null;
     SMLog.Error(error, this.File);
 }
Esempio n. 6
0
        /// <summary>
        /// Called when the server is about to shut down.
        /// </summary>
        private void OnGameShutdown()
        {
            PluginManager.IsLocked = true;
            foreach (var k in PluginManager.Plugins.Keys.ToArray())
            {
                if (PluginManager.Plugins.TryGetValue(k, out var plugin) && plugin.LoadStatus == PluginContainer.Status.Loaded)
                {
                    try
                    {
                        plugin.Plugin.OnGameShutdown();
                    }
                    catch (HaltPluginException)
                    {
                    }
                    catch (Exception e)
                    {
                        plugin.SetFailState(e);
                    }
                }
            }

            PluginManager.IsLocked = false;
            PluginManager.UnloadAll();
            SMLog.Close();
        }
Esempio n. 7
0
 /// <summary>
 /// Raises the <see cref="Ended"/> event.
 /// </summary>
 /// <param name="counts">The count of votes for each answer option.</param>
 /// <param name="percents">The percentage of eligible voters that voted for each answer option.</param>
 private void OnVoteEnded(int[] counts, float[] percents)
 {
     if (this.Ended != null)
     {
         var args = new VoteEndedEventArgs(this, this.voteOptions, counts, percents, this.data);
         foreach (EventHandler <VoteEndedEventArgs> d in this.Ended.GetInvocationList())
         {
             try
             {
                 d.Invoke(this, args);
             }
             catch (HaltPluginException)
             {
             }
             catch (Exception e)
             {
                 if (d.Target is IPlugin p)
                 {
                     p.Container.SetFailState(e);
                 }
                 else
                 {
                     SMLog.Error(e);
                 }
             }
         }
     }
 }
Esempio n. 8
0
 /// <summary>
 /// Executes the admin command.
 /// </summary>
 /// <param name="arguments">The list of arguments for the command.</param>
 /// <param name="client">The <see cref="ClientInfo"/> object representing the client that is executing the command.</param>
 internal void OnExecute(List <string> arguments, ClientInfo client)
 {
     if (this.Executed != null)
     {
         var args = new AdminCommandEventArgs(this, arguments, client);
         foreach (EventHandler <AdminCommandEventArgs> d in this.Executed.GetInvocationList())
         {
             try
             {
                 d.Invoke(this, args);
             }
             catch (HaltPluginException)
             {
             }
             catch (Exception e)
             {
                 if (d.Target is IPlugin p)
                 {
                     p.Container.SetFailState(e);
                 }
                 else
                 {
                     SMLog.Error(e);
                 }
             }
         }
     }
 }
Esempio n. 9
0
        /// <summary>
        /// Processes a chat message.
        /// </summary>
        /// <param name="client">The <see cref="ClientInfo"/> object representing the client that sent the message.</param>
        /// <param name="type">The type of chat message.</param>
        /// <param name="message">The message text.</param>
        /// <param name="recipientEntityIds">The list of entity IDs receiving the message.</param>
        /// <returns><c>true</c> to allow the message to continue propagating; <c>false</c> to consume the message.</returns>
        internal static bool HookChatMessage(ClientInfo client, EChatType type, string message, List <int> recipientEntityIds)
        {
            if (client == null)
            {
                return(true);
            }

            if (ChatMessage != null)
            {
                var args = new ChatMessageEventArgs(client, type, message, recipientEntityIds);
                foreach (EventHandler <ChatMessageEventArgs> d in ChatMessage.GetInvocationList())
                {
                    try
                    {
                        d.Invoke(null, args);
                        if (args.Handled)
                        {
                            return(false);
                        }
                    }
                    catch (HaltPluginException)
                    {
                        args.Handled = false;
                    }
                    catch (Exception e)
                    {
                        args.Handled = false;
                        if (d.Target is IPlugin p)
                        {
                            p.Container.SetFailState(e);
                        }
                        else
                        {
                            SMLog.Error(e);
                        }
                    }
                }
            }

            if (message.StartsWith(publicChatTrigger.AsString) || message.StartsWith(silentChatTrigger.AsString))
            {
                replyToChat.Add(client.entityId);
                ConnectionManager.Instance.ServerConsoleCommand(client, $"sm {message.Substring(1)}");
                replyToChat.Remove(client.entityId);

                return(message.StartsWith(publicChatTrigger.AsString));
            }

            return(true);
        }
Esempio n. 10
0
        /// <summary>
        /// Executes a single automatically executed configuration file.
        /// </summary>
        /// <param name="config">The <see cref="ConfigInfo"/> object containing the configuration file metadata.</param>
        private static void ExecuteConfig(ConfigInfo config)
        {
            var path = $"{SMPath.Config}{config.Name}.xml";

            if (!File.Exists(path))
            {
                if (!config.AutoCreate)
                {
                    return;
                }

                GenerateConfig(config);
            }

            var xml = new XmlDocument();

            try
            {
                xml.Load(path);
            }
            catch (XmlException e)
            {
                SMLog.Error($"Failed reading configuration from {path}: {e.Message}");
                return;
            }

            foreach (XmlElement element in xml.GetElementsByTagName("property"))
            {
                if (element.HasAttribute("name") && element.HasAttribute("value"))
                {
                    if (conVars.TryGetValue(element.GetAttribute("name").Trim().ToLower(), out var conVar))
                    {
                        conVar.Value.Value = element.GetAttribute("value");
                    }
                }
            }

            if (watcher == null)
            {
                watcher = new FileSystemWatcher(SMPath.Config, "*.xml")
                {
                    NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName,
                };
                watcher.Changed            += OnConfigFileChanged;
                watcher.Deleted            += OnConfigFileChanged;
                watcher.Renamed            += OnConfigFileChanged;
                watcher.EnableRaisingEvents = true;
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Loads the files for a set of phrases.
        /// </summary>
        /// <param name="file">The name of the translation file.</param>
        private static void LoadPhrases(string file)
        {
            var xml = new XmlDocument();

            foreach (var path in Directory.GetFiles(SMPath.Translations, $"{file}.xml", SearchOption.AllDirectories))
            {
                try
                {
                    xml.Load(path);
                }
                catch (XmlException e)
                {
                    SMLog.Error($"Failed reading translation file from {path}: {e.Message}");
                    continue;
                }

                foreach (XmlElement phraseElement in xml.GetElementsByTagName("Phrase"))
                {
                    if (!phraseElement.HasAttribute("Name"))
                    {
                        continue;
                    }

                    var key = phraseElement.GetAttribute("Name");
                    if (phrases.ContainsKey(key))
                    {
                        SMLog.Error($"Phrase \"{key}\" in file {file}.xml conflicts with file {phrases[key].File}.xml");
                        continue;
                    }

                    var pd = new PhraseDictionary(file, key);
                    foreach (XmlElement formatElement in phraseElement.GetElementsByTagName("Format"))
                    {
                        var mc = Regex.Matches(formatElement.InnerText, @"\{([1-9][0-9]*)\:([0-9a-zA-Z]+)\}");
                        if (mc.Count == 0)
                        {
                            throw new Exception($"Invalid format string for translation file {file}: {formatElement.InnerText}");
                        }

                        foreach (Match m in mc)
                        {
                            pd.FormatArgs[int.Parse(m.Groups[1].Value)] = m.Groups[2].Value;
                        }

                        break;
                    }

                    foreach (var langElement in phraseElement.ChildNodes)
                    {
                        if (langElement is XmlElement)
                        {
                            var lang         = ((XmlElement)langElement).Name;
                            var phraseString = ((XmlElement)langElement).InnerText;
                            if (lang.Equals("Format"))
                            {
                                continue;
                            }

                            pd[lang] = phraseString;
                        }
                    }

                    phrases[key] = pd;
                }
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Loads a plugin.
        /// </summary>
        /// <param name="key">The dictionary key of the plugin.</param>
        /// <param name="refreshing">A value indicating whether the plugin list is being refreshed.</param>
        private static void Load(string key, bool refreshing)
        {
            if (IsLocked)
            {
                throw new NotSupportedException();
            }

            if (Plugins.ContainsKey(key) && Plugins[key].LoadStatus == PluginContainer.Status.Loaded)
            {
                return;
            }

            var file = $"{SMPath.Plugins}{key}.dll";

            if (!File.Exists(file))
            {
                return;
            }

            try
            {
                var dll       = Assembly.Load(File.ReadAllBytes(file));
                var type      = dll.GetType($"SevenMod.Plugin.{key}.{key}", true, true);
                var container = new PluginContainer(Path.GetFileName(file));
                if (type.IsSubclassOf(PluginParentType))
                {
                    try
                    {
                        var plugin = Activator.CreateInstance(type) as PluginAbstract;
                        plugin.Container = container;
                        plugin.OnLoadPlugin();
                        if (API.IsGameAwake)
                        {
                            plugin.OnGameAwake();
                        }

                        if (API.IsGameStartDone)
                        {
                            plugin.OnGameStartDone();
                        }

                        if (ConVarManager.ConfigsLoaded)
                        {
                            ConVarManager.ExecuteConfigs(plugin);
                            plugin.OnConfigsExecuted();
                        }

                        if (!refreshing)
                        {
                            AdminManager.ReloadAdmins();
                        }

                        container.Plugin     = plugin;
                        container.PluginInfo = plugin.Info;
                        container.LoadStatus = PluginContainer.Status.Loaded;
                    }
                    catch (HaltPluginException)
                    {
                        throw;
                    }
                    catch (Exception e)
                    {
                        container.LoadStatus = PluginContainer.Status.Error;
                        container.Error      = e.Message;
                        throw;
                    }

                    Plugins[key] = container;
                }
                else
                {
                    throw new Exception($"{type.Name} does not inherit from {PluginParentType.Name}");
                }
            }
            catch (Exception e)
            {
                SMLog.Error($"Failed loading plugin {key}.dll: {e.Message}");
                SMLog.Error(e);
            }
        }
Esempio n. 13
0
 /// <summary>
 /// Logs an action performed by an admin.
 /// </summary>
 /// <param name="client">The <see cref="SMClient"/> representing the client performing the action, if applicable.</param>
 /// <param name="target">The <see cref="SMClient"/> representing the target of the action, if applicable.</param>
 /// <param name="message">The message describing the action.</param>
 /// <param name="args">The arguments for <paramref name="message"/>.</param>
 protected void LogAction(SMClient client, SMClient target, string message, params object[] args)
 {
     SMLog.LogAction(this, client?.ClientInfo, target?.ClientInfo, message, args);
 }
Esempio n. 14
0
 /// <summary>
 /// Logs a message to the SevenMod error logs.
 /// </summary>
 /// <param name="message">The error message to log.</param>
 protected void LogError(string message)
 {
     SMLog.Error(message, this.Container.File);
 }
Esempio n. 15
0
 /// <summary>
 /// Logs a message to the SevenMod logs.
 /// </summary>
 /// <param name="message">The message to log.</param>
 protected void LogMessage(string message)
 {
     SMLog.Out(message, this.Container.File);
 }
Esempio n. 16
0
        /// <summary>
        /// Parses the database configuration file and loads the list of connection configurations.
        /// </summary>
        private static void ParseConfig()
        {
            connections.Clear();

            if (!File.Exists(ConfigPath))
            {
                CreateConfig();
            }

            var xml = new XmlDocument();

            try
            {
                xml.Load(ConfigPath);
            }
            catch (XmlException e)
            {
                SMLog.Error($"Failed reading database configuration from {ConfigPath}: {e.Message}");
                return;
            }

            var defaultDriver         = DatabaseDriver.SQLite;
            var defaultDriverElements = xml.GetElementsByTagName("DefaultDriver");

            if ((defaultDriverElements.Count > 0) && "mysql".EqualsCaseInsensitive(defaultDriverElements[0].InnerText))
            {
                defaultDriver = DatabaseDriver.MySQL;
            }

            foreach (XmlElement element in xml.GetElementsByTagName("Connection"))
            {
                if (!element.HasAttribute("Name"))
                {
                    continue;
                }

                var name = element.GetAttribute("Name");
                if (connections.ContainsKey(name))
                {
                    continue;
                }

                var driver         = defaultDriver;
                var driverElements = element.GetElementsByTagName("Driver");
                if (driverElements.Count > 0)
                {
                    if ("sqlite".EqualsCaseInsensitive(driverElements[0].InnerText))
                    {
                        driver = DatabaseDriver.SQLite;
                    }
                    else if ("mysql".EqualsCaseInsensitive(driverElements[0].InnerText))
                    {
                        driver = DatabaseDriver.MySQL;
                    }
                    else
                    {
                        continue;
                    }
                }

                var databaseElements = element.GetElementsByTagName("Database");
                if (databaseElements.Count == 0)
                {
                    continue;
                }

                var database = databaseElements[0].InnerText;

                if (driver == DatabaseDriver.MySQL)
                {
                    var hostElements = element.GetElementsByTagName("Host");
                    if (hostElements.Count == 0)
                    {
                        continue;
                    }

                    var host = hostElements[0].InnerText;

                    var userElements = element.GetElementsByTagName("User");
                    if (userElements.Count == 0)
                    {
                        continue;
                    }

                    var user = userElements[0].InnerText;

                    var pass         = string.Empty;
                    var passElements = element.GetElementsByTagName("Pass");
                    if (passElements.Count > 0)
                    {
                        pass = passElements[0].InnerText;
                    }

                    var port         = 3306u;
                    var portElements = element.GetElementsByTagName("Port");
                    if (passElements.Count > 0)
                    {
                        uint.TryParse(portElements[0].InnerText, out port);
                    }

                    var connection = new ConnectionInfo(DatabaseDriver.MySQL, database, host, user, pass, port);
                    connections.Add(name, connection);
                }
                else
                {
                    var connection = new ConnectionInfo(DatabaseDriver.SQLite, database);
                    connections.Add(name, connection);
                }
            }

            if (watcher == null)
            {
                watcher = new FileSystemWatcher(Path.GetDirectoryName(ConfigPath), Path.GetFileName(ConfigPath))
                {
                    NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite,
                };
                watcher.Changed            += OnConfigFileChanged;
                watcher.Deleted            += OnConfigFileChanged;
                watcher.Renamed            += OnConfigFileChanged;
                watcher.EnableRaisingEvents = true;
            }
        }