diff --git a/CHANGELOG.md b/CHANGELOG.md index 22e9ca07..35263cf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin * Do not forget to sign every line you change with your name. (@hakusaro) * If there is no section called "Upcoming changes" below this line, please add one with `## Upcoming changes` as the first line, and then a bulleted item directly after with the first change. +## Upcoming changes (TShock 5.0.0) +* Reduced load/save console spam. (@SignatureBeef, @YehnBeep) + ## Upcoming changes ## TShock 4.5.15 diff --git a/TShockAPI/Modules/Module.cs b/TShockAPI/Modules/Module.cs new file mode 100644 index 00000000..20bef23b --- /dev/null +++ b/TShockAPI/Modules/Module.cs @@ -0,0 +1,34 @@ +/* +TShock, a server mod for Terraria +Copyright (C) 2011-2019 Pryaxis & TShock Contributors + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +using System; +namespace TShockAPI.Modules +{ + public abstract class Module : IDisposable + { + /// + /// Entry point of the module + /// + public abstract void Initialise(); + + /// + /// Resource cleanup, e.g. hooks and events + /// + public virtual void Dispose() { } + } +} + diff --git a/TShockAPI/Modules/ModuleManager.cs b/TShockAPI/Modules/ModuleManager.cs new file mode 100644 index 00000000..c1458fb6 --- /dev/null +++ b/TShockAPI/Modules/ModuleManager.cs @@ -0,0 +1,101 @@ +/* +TShock, a server mod for Terraria +Copyright (C) 2011-2019 Pryaxis & TShock Contributors + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace TShockAPI.Modules +{ + public class ModuleManager : IDisposable + { + private List _modules = new(); + + /// + /// Discovers derived classes from across the assembly + /// + /// Type definitions of the modules that can be created + IEnumerable CollectModules() => Assembly.GetExecutingAssembly() + .GetTypes() + .Where(t => typeof(Module).IsAssignableFrom(t) && !t.IsAbstract) + ; + + /// + /// Initialises derived classes defined across the assembly + /// + /// Additional constructor arguments allowed for modules + public void Initialise(object[] parameters) + { + foreach (var moduleType in CollectModules()) + InitialiseModule(moduleType, parameters); + } + + /// + /// Initialises a module by its type definition + /// + /// The type of the module + /// Additional constructor arguments allowed for modules + public void InitialiseModule(Type moduleType, object[] parameters) + { + if (!typeof(Module).IsAssignableFrom(moduleType)) + throw new NotSupportedException($"Cannot load module {moduleType.FullName} as it does not derive from {typeof(Module).FullName}"); + + var args = new List(); + ConstructorInfo constructor = null; + + foreach (var ctor in moduleType.GetConstructors()) + { + args.Clear(); + var ctorParams = ctor.GetParameters(); + + foreach (var prm in ctorParams) + { + var matching_objects = parameters.Where(p => prm.ParameterType.IsAssignableFrom(p.GetType())); + if (matching_objects.Count() == 1) + args.Add(matching_objects.Single()); + else + { + // skip this ctor since we cannot find a suitable parameter for it. + break; + } + } + + if (args.Count() == ctorParams.Length) + constructor = ctor; + } + + if (constructor is not null) + { + var module = (Module)constructor.Invoke(args.ToArray()); + _modules.Add(module); + module.Initialise(); + } + } + + /// + /// Disposes of the module and the manager instance + /// + public void Dispose() + { + foreach (var module in _modules) + module.Dispose(); + _modules.Clear(); + } + } +} + diff --git a/TShockAPI/Modules/ReduceConsoleSpam.cs b/TShockAPI/Modules/ReduceConsoleSpam.cs new file mode 100644 index 00000000..bc33655c --- /dev/null +++ b/TShockAPI/Modules/ReduceConsoleSpam.cs @@ -0,0 +1,66 @@ +/* +TShock, a server mod for Terraria +Copyright (C) 2011-2019 Pryaxis & TShock Contributors + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +using System; + +namespace TShockAPI.Modules +{ + public class ReduceConsoleSpam : Module + { + public override void Initialise() => + OTAPI.Hooks.Main.StatusTextChange += OnMainStatusTextChange; + + public override void Dispose() => + OTAPI.Hooks.Main.StatusTextChange -= OnMainStatusTextChange; + + /// + /// Holds the last status text value, to determine if there is a suitable change to report. + /// + private string _lastStatusText = null; + + /// + /// Aims to reduce the amount of console spam by filtering out load/save progress + /// + /// + /// OTAPI event + private void OnMainStatusTextChange(object sender, OTAPI.Hooks.Main.StatusTextChangeArgs e) + { + bool replace(string text) + { + if (e.Value.StartsWith(text)) + { + var segment = e.Value.Substring(0, text.Length); + if (_lastStatusText != segment) + { + Console.WriteLine(segment); // write it manually instead of terraria which causes double writes + _lastStatusText = segment; + } + e.Value = ""; + return true; + } + return false; + } + + _ = replace("Resetting game objects") + || replace("Settling liquids") + || replace("Loading world data") + || replace("Saving world data") + || replace("Validating world save"); + } + } +} + diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index 27e170d2..798b5a5b 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -46,6 +46,7 @@ using TShockAPI.Localization; using TShockAPI.Configuration; using Terraria.GameContent.Creative; using System.Runtime.InteropServices; +using TShockAPI.Modules; namespace TShockAPI { @@ -149,6 +150,8 @@ namespace TShockAPI /// public static event Action Initialized; + public static ModuleManager ModuleManager { get; } = new ModuleManager(); + /// Version - The version required by the TerrariaAPI to be passed back for checking & loading the plugin. /// value - The version number specified in the Assembly, based on the VersionNum variable set in this class. public override Version Version @@ -421,6 +424,8 @@ namespace TShockAPI EnglishLanguage.Initialize(); + ModuleManager.Initialise(new object[] { this }); + if (Config.Settings.RestApiEnabled) RestApi.Start(); @@ -463,6 +468,8 @@ namespace TShockAPI } SaveManager.Instance.Dispose(); + ModuleManager.Dispose(); + ServerApi.Hooks.GamePostInitialize.Deregister(this, OnPostInit); ServerApi.Hooks.GameUpdate.Deregister(this, OnUpdate); ServerApi.Hooks.GameHardmodeTileUpdate.Deregister(this, OnHardUpdate);