From d09ef8214de31e95b6766a8eb2e77879e9330b13 Mon Sep 17 00:00:00 2001 From: SentorX Date: Thu, 27 Apr 2023 16:09:44 +0200 Subject: [PATCH 1/3] Migrating class views to self load... not done. --- RPGPlugin.csproj | 8 +-- RPGPlugin/RPGPlugin.cs | 52 +++++++++++--------- RPGPlugin/RPGPluginCommands.cs | 13 ++--- RPGPlugin/Roles/Config/HunterConfig.cs | 34 ++++++++++--- RPGPlugin/Roles/Config/MinerConfig.cs | 18 ++++--- RPGPlugin/Roles/Config/SampleConfig.cs | 9 ++-- RPGPlugin/Roles/Config/WarriorConfig.cs | 22 +++++---- RPGPlugin/Roles/Config/configBase.cs | 8 +-- RPGPlugin/Roles/View/HunterView.xaml | 12 +++++ RPGPlugin/Roles/View/HunterView.xaml.cs | 12 +++++ RPGPlugin/Torch GUI/EditItemWindow.xaml.cs | 2 + RPGPlugin/Torch GUI/RPGPluginControl.xaml.cs | 43 ++++++++++++++-- RPGPlugin/Utils/HelperFunctions.cs | 19 +++++++ RPGPlugin/Utils/RPGPluginConfig.cs | 1 + RPGPlugin/Utils/RoleManager.cs | 13 +++-- 15 files changed, 195 insertions(+), 71 deletions(-) create mode 100644 RPGPlugin/Roles/View/HunterView.xaml create mode 100644 RPGPlugin/Roles/View/HunterView.xaml.cs create mode 100644 RPGPlugin/Utils/HelperFunctions.cs diff --git a/RPGPlugin.csproj b/RPGPlugin.csproj index efdfb3c..98cf4bf 100644 --- a/RPGPlugin.csproj +++ b/RPGPlugin.csproj @@ -138,6 +138,9 @@ + + HunterView.xaml + @@ -151,6 +154,7 @@ RPGPluginControl.xaml + @@ -179,6 +183,7 @@ Designer MSBuild:Compile + MSBuild:Compile Designer @@ -196,9 +201,6 @@ Designer - - - diff --git a/RPGPlugin/RPGPlugin.cs b/RPGPlugin/RPGPlugin.cs index 2899281..e347512 100644 --- a/RPGPlugin/RPGPlugin.cs +++ b/RPGPlugin/RPGPlugin.cs @@ -3,6 +3,8 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; +using System.Threading; +using System.Threading.Tasks; using System.Timers; using System.Windows.Controls; using System.Xml.Serialization; @@ -19,7 +21,8 @@ using VRage.GameServices; using RPGPlugin.Utils; using Sandbox.Game.Multiplayer; -using Newtonsoft.Json; +using Torch.Collections; +using Timer = System.Timers.Timer; namespace RPGPlugin @@ -31,6 +34,7 @@ public class Roles : TorchPluginBase, IWpfPlugin public static Dictionary classConfigs = new Dictionary(); public static Dictionary roles = new Dictionary(); private Timer _delayManagers = new Timer(TimeSpan.FromSeconds(5).TotalMilliseconds); + public MtObservableCollection, TabItem> ClassViews = new MtObservableList(); public PatchManager patchManager; public PatchContext patchContext; public static IChatManagerServer ChatManager => Instance.Torch.CurrentSession.Managers.GetManager(); @@ -45,14 +49,11 @@ public class Roles : TorchPluginBase, IWpfPlugin private Persistent _config; public RPGPluginConfig Config => _config?.Data; - public override void Init(ITorchBase torch) + public override async void Init(ITorchBase torch) { base.Init(torch); Instance = this; - SetupConfig(); - - // Registration of role configuration classes - // This is called on class auto-load! + await SetupConfig(); _delayManagers.Stop(); _delayManagers.Elapsed += DelayManagersOnElapsed; @@ -62,12 +63,11 @@ public override void Init(ITorchBase torch) else Log.Warn("No session manager loaded!"); - patchManager = DependencyProviderExtensions.GetManager(torch.Managers); + patchManager = torch.Managers.GetManager(); patchContext = patchManager.AcquireContext(); DrillPatch.Patch(patchContext); - RoleAgent.LoadAllConfigs(); - RoleAgent.LoadAllClasses(); - Save(); + await Save(); + await WaitThenSetupClasses(); } private void DelayManagersOnElapsed(object sender, ElapsedEventArgs e) @@ -148,7 +148,7 @@ private static void PlayerConnected(ulong steamID, string s) PlayerManagers.TryAdd(steamID, roleManager); } - private void SetupConfig() + private async Task SetupConfig() { string dataPath = Path.Combine(StoragePath, "RPGPlugin"); string playerDataPath = Path.Combine(dataPath, "Player Data"); @@ -156,13 +156,6 @@ private void SetupConfig() // create directories if they do not exist Directory.CreateDirectory(dataPath); Directory.CreateDirectory(playerDataPath); - - // set the config file path - // we prefer xml over json because it is easier to edit for the user.. - // most users are not experienced with json format. xml is more familiar. - // the class config are fine as json as they really don't need to be edited by the user. - // any issues serializing to xml can be fixed by implementing a serializable version of - // what doesnt have ISerializable implemented. string configFile = Path.Combine(StoragePath, "RPGPluginConfig.xml"); if (!File.Exists(configFile)) @@ -179,7 +172,6 @@ private void SetupConfig() catch (Exception e) { Log.Warn(e); - } if (_config?.Data == null) @@ -203,24 +195,38 @@ private void SetupConfig() { Log.Warn(e); } - Save(); + await Save(); } } } - - - public void Save() + public Task Save() { try { _config.Save(); Log.Info("Main Configuration Saved."); + return Task.CompletedTask; } catch (IOException e) { Log.Warn(e, "Main Configuration Saved during plugin loading."); + return Task.FromException(e); } } + + private async Task WaitThenSetupClasses() + { + await Task.Run(async () => + { + while (Config == null) + { + Thread.Sleep(1000); + } + await RoleAgent.LoadAllConfigs(); + await RoleAgent.LoadAllClasses(); + }); + + } } } diff --git a/RPGPlugin/RPGPluginCommands.cs b/RPGPlugin/RPGPluginCommands.cs index d76bf6a..57abcbe 100644 --- a/RPGPlugin/RPGPluginCommands.cs +++ b/RPGPlugin/RPGPluginCommands.cs @@ -15,7 +15,7 @@ public class RolesCommands : CommandModule [Command("setrole", "Set your role")] [Permission(MyPromoteLevel.None)] - public void SetRole(string roleName) + public async void SetRole(string roleName) { if (Context.Player == null) { @@ -36,11 +36,8 @@ public void SetRole(string roleName) } // Check if the role is valid - if (!Roles.Instance.Config.RegisteredRoles.Any(r => r.Item1.Equals(roleName, StringComparison.OrdinalIgnoreCase))) + if (Roles.Instance.Config.RegisteredRoles.Any(r => r.Item1.Equals(roleName, StringComparison.OrdinalIgnoreCase))) { - - if (roleName != Roles.Instance.Config.RegisteredRoles[index].Item1) continue; - Roles.PlayerManagers[Context.Player.SteamUserId].SetRole(roleName); await Roles.PlayerManagers[Context.Player.SteamUserId].SavePlayerData(); Context.Respond($"Your role has been updated to [{roleName}]"); @@ -95,9 +92,9 @@ public void Stats() StringBuilder reply = new StringBuilder(); reply.AppendLine("*** Information ***"); - reply.AppendLine("—————————————————————————————"); + reply.AppendLine("—————————————————————————"); reply.AppendLine($"Current Role: {currentPlayerRole}"); - reply.AppendLine("—————————————————————————————"); + reply.AppendLine("—————————————————————————"); foreach (SerializableTuple role in Roles.Instance.Config.RegisteredRoles) { if (!Roles.PlayerManagers[Context.Player.SteamUserId]._PlayerData.ClassInfo.ContainsKey(role.Item1)) @@ -109,7 +106,7 @@ public void Stats() reply.AppendLine($"{role.Item1}:"); reply.AppendLine($"Current level: {Roles.PlayerManagers[Context.Player.SteamUserId]._PlayerData.ClassInfo[role.Item1].Item1}."); reply.AppendLine($"Exp needed for next level: {Roles.roles[role.Item1 + "Class"].ExpToLevelUp(Context.Player.SteamUserId).ToString()}."); - reply.AppendLine("—————————————————————————————"); + reply.AppendLine("—————————————————————————"); } Context.Respond(reply.ToString()); diff --git a/RPGPlugin/Roles/Config/HunterConfig.cs b/RPGPlugin/Roles/Config/HunterConfig.cs index 933aaf2..3252ff0 100644 --- a/RPGPlugin/Roles/Config/HunterConfig.cs +++ b/RPGPlugin/Roles/Config/HunterConfig.cs @@ -1,9 +1,14 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; +using System.Threading; using System.Threading.Tasks; +using System.Windows.Controls; using Newtonsoft.Json; using RPGPlugin.Utils; +using RPGPlugin.View; +using static RPGPlugin.Utils.StaticHelperFunctions; namespace RPGPlugin { @@ -18,29 +23,46 @@ public sealed class HunterConfig : configBase public override ObservableCollection> SkillPoints { get; set; } = new ObservableCollection>(); - public override void init() + public override Task init() { // Initialize class with default settings, will be replaced if a config file is loaded. ExpRatio.Add(new KeyValuePair("Wolf", 0.0013 )); ExpRatio.Add(new KeyValuePair("Spider", 0.0013 )); ExpRatio.Add(new KeyValuePair("SmallBlock", 2 )); ExpRatio.Add(new KeyValuePair("LargeBlock", 10 )); + + // Init View + + StaThreadWrapper(() => + { + UserControl view = new HunterView(); + view.Visibility = System.Windows.Visibility.Visible; + TabItem item = new TabItem {Header = "Hunter", Content = view}; + + Roles.Instance.ClassViews.Add(item); + }); + + return Task.CompletedTask; } - public override void RegisterClass() + public override Task RegisterClass() { + // Register Class Info SerializableTuple RoleToRegister = new SerializableTuple{Item1 = "Hunter", Item2 = "Specialized in attacking NPC ships and creatures."}; + if (Roles.Instance.Config.RegisteredRoles.Any(role => role.Item1.Equals(RoleToRegister.Item1, StringComparison.OrdinalIgnoreCase))) return Task.CompletedTask; + Roles.Instance.Config.RegisteredRoles.Add(RoleToRegister); + Roles.Log.Warn($"Registered New Class: {RoleToRegister.Item1}"); - if (!Roles.Instance.Config.RegisteredRoles.Contains(RoleToRegister)) - Roles.Instance.Config.RegisteredRoles.Add(RoleToRegister); + return Task.CompletedTask; } - public override void LoadConfig() + public override Task LoadConfig() { string data = GetConfig().Result; - if (data == null) return; + if (data == null) return Task.CompletedTask; HunterConfig classConfig = JsonConvert.DeserializeObject(data); ExpRatio = classConfig.ExpRatio; + return Task.CompletedTask; } public override async Task SaveConfig() diff --git a/RPGPlugin/Roles/Config/MinerConfig.cs b/RPGPlugin/Roles/Config/MinerConfig.cs index 7e315c5..8521da9 100644 --- a/RPGPlugin/Roles/Config/MinerConfig.cs +++ b/RPGPlugin/Roles/Config/MinerConfig.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using System.Threading.Tasks; using Newtonsoft.Json; using RPGPlugin.Utils; @@ -19,7 +20,7 @@ public sealed class MinerConfig : configBase public override ObservableCollection> SkillPoints { get; set; } = new ObservableCollection>(); - public override void init() + public override Task init() { base.init(); // Set defaults, will be used if no config file has been created or becomes corrupt. @@ -34,24 +35,29 @@ public override void init() ExpRatio.Add(new KeyValuePair( "Platinum", 0.28 )); ExpRatio.Add(new KeyValuePair( "Uranium", 0.30 )); ExpRatio.Add(new KeyValuePair( "Ice", 0.135 )); + return Task.CompletedTask; } - public override void RegisterClass() + public override Task RegisterClass() { SerializableTuple RoleToRegister = new SerializableTuple{Item1 = "Miner", Item2 = "Specialized in resource extraction."}; + + if (Roles.Instance.Config.RegisteredRoles.Any(Role => Role.Item1.Equals(RoleToRegister.Item1, StringComparison.OrdinalIgnoreCase))) return Task.CompletedTask; - if (!Roles.Instance.Config.RegisteredRoles.Contains(RoleToRegister)) - Roles.Instance.Config.RegisteredRoles.Add(RoleToRegister); + Roles.Instance.Config.RegisteredRoles.Add(RoleToRegister); + Roles.Log.Warn($"Registered New Class: {RoleToRegister.Item1}"); + return Task.CompletedTask; } - public override void LoadConfig() + public override Task LoadConfig() { string data = GetConfig().Result; - if (data == null) return; + if (data == null) return Task.CompletedTask; MinerConfig classConfig = JsonConvert.DeserializeObject(data); ExpRatio = classConfig.ExpRatio; + return Task.CompletedTask; } public override async Task SaveConfig() diff --git a/RPGPlugin/Roles/Config/SampleConfig.cs b/RPGPlugin/Roles/Config/SampleConfig.cs index 0d6060b..8850bcc 100644 --- a/RPGPlugin/Roles/Config/SampleConfig.cs +++ b/RPGPlugin/Roles/Config/SampleConfig.cs @@ -15,7 +15,7 @@ public class SampleConfig : configBase public override ObservableCollection> SkillPoints { get; set; } = new ObservableCollection>(); - public override void init() + public override Task init() { // Always run this method first! // base.init(); @@ -23,9 +23,10 @@ public override void init() // Set your default XP values here, they will load before your config fill // will, and will be used if no config file has been created at this point. // See MinerClass for an example. + return Task.CompletedTask; } - public override void LoadConfig() + public override Task LoadConfig() { // This will load your default settings when called. If none exist you // should create default settings in a new method. @@ -33,6 +34,7 @@ public override void LoadConfig() // Returns your config file in json format if it exists, null if not. // string data = GetConfig().Result; // if (data == null) return; + return Task.CompletedTask; } public override Task SaveConfig() @@ -46,7 +48,7 @@ public override Task SaveConfig() return Task.CompletedTask; } - public override void RegisterClass() + public override Task RegisterClass() { /* Tuple RoleToRegister = new Tuple("This Is The Class Title", "This Is A Description Of The Class"); @@ -54,6 +56,7 @@ public override void RegisterClass() if (!Roles.Instance.Config.RegisteredRoles.Contains(RoleToRegister)) Roles.Instance.Config.RegisteredRoles.Add(RoleToRegister); */ + return Task.CompletedTask; } } } \ No newline at end of file diff --git a/RPGPlugin/Roles/Config/WarriorConfig.cs b/RPGPlugin/Roles/Config/WarriorConfig.cs index 4817896..a70dabe 100644 --- a/RPGPlugin/Roles/Config/WarriorConfig.cs +++ b/RPGPlugin/Roles/Config/WarriorConfig.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using System.Threading.Tasks; using Newtonsoft.Json; using RPGPlugin.Utils; @@ -18,7 +19,7 @@ public sealed class WarriorConfig : configBase public override ObservableCollection> SkillPoints { get; set; } = new ObservableCollection>(); - public override void init() + public override Task init() { // Initialize class with default settings, will be replaced if a config file is loaded. ExpRatio.Add(new KeyValuePair("EnemyPlayer", 25 )); @@ -31,25 +32,27 @@ public override void init() //test skill point system SkillPoints.Add(new KeyValuePair(2, 1)); + return Task.CompletedTask; } - public override void RegisterClass() + public override Task RegisterClass() { SerializableTuple RoleToRegister = new SerializableTuple{Item1 = "Warrior", Item2 = "Specialized in battles and destruction of other engineers things!."}; + + if (Roles.Instance.Config.RegisteredRoles.Any(Role => Role.Item1.Equals(RoleToRegister.Item1, StringComparison.OrdinalIgnoreCase))) return Task.CompletedTask; - if (!Roles.Instance.Config.RegisteredRoles.Contains(RoleToRegister)) - Roles.Instance.Config.RegisteredRoles.Add(RoleToRegister); - else - Roles.Log.Warn("Warior Role already registered!"); - + Roles.Instance.Config.RegisteredRoles.Add(RoleToRegister); + Roles.Log.Warn($"Registered New Class: {RoleToRegister.Item1}"); + return Task.CompletedTask; } - public override void LoadConfig() + public override Task LoadConfig() { string data = GetConfig().Result; - if (data == null) return; + if (data == null) return Task.CompletedTask; WarriorConfig classConfig = JsonConvert.DeserializeObject(data); ExpRatio = classConfig.ExpRatio; + return Task.CompletedTask; } public override async Task SaveConfig() @@ -57,6 +60,5 @@ public override async Task SaveConfig() string jsonData = JsonConvert.SerializeObject(this, Formatting.Indented); await SaveConfig(jsonData); } - } } \ No newline at end of file diff --git a/RPGPlugin/Roles/Config/configBase.cs b/RPGPlugin/Roles/Config/configBase.cs index 3d05243..693a733 100644 --- a/RPGPlugin/Roles/Config/configBase.cs +++ b/RPGPlugin/Roles/Config/configBase.cs @@ -29,15 +29,15 @@ public abstract class configBase /// /// Initializer, always start with base.int(). This sets the config file save location and name. /// - public virtual void init() + public virtual Task init() { - + return Task.CompletedTask; } /// /// Register the class type in the master list! /// - public abstract void RegisterClass(); + public abstract Task RegisterClass(); protected virtual string GetFileName() { @@ -48,7 +48,7 @@ protected virtual string GetFileName() /// /// GetConfig().Results returns your your config data as json. /// - public abstract void LoadConfig(); + public abstract Task LoadConfig(); /// /// The following SHOULD work in most cases: diff --git a/RPGPlugin/Roles/View/HunterView.xaml b/RPGPlugin/Roles/View/HunterView.xaml new file mode 100644 index 0000000..56f50d7 --- /dev/null +++ b/RPGPlugin/Roles/View/HunterView.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/RPGPlugin/Roles/View/HunterView.xaml.cs b/RPGPlugin/Roles/View/HunterView.xaml.cs new file mode 100644 index 0000000..c79e8ac --- /dev/null +++ b/RPGPlugin/Roles/View/HunterView.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace RPGPlugin.View +{ + public partial class HunterView : UserControl + { + public HunterView() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/RPGPlugin/Torch GUI/EditItemWindow.xaml.cs b/RPGPlugin/Torch GUI/EditItemWindow.xaml.cs index 6af2ec5..837a30f 100644 --- a/RPGPlugin/Torch GUI/EditItemWindow.xaml.cs +++ b/RPGPlugin/Torch GUI/EditItemWindow.xaml.cs @@ -1,5 +1,7 @@ using System.Globalization; using System.Windows; +using System.Windows.Controls; +using RPGPlugin.Utils; namespace RPGPlugin { diff --git a/RPGPlugin/Torch GUI/RPGPluginControl.xaml.cs b/RPGPlugin/Torch GUI/RPGPluginControl.xaml.cs index bbb33cf..728ddfb 100644 --- a/RPGPlugin/Torch GUI/RPGPluginControl.xaml.cs +++ b/RPGPlugin/Torch GUI/RPGPluginControl.xaml.cs @@ -1,20 +1,53 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Collections.Specialized; using System.Diagnostics; +using System.Net.Mime; +using System.Timers; using System.Windows; using System.Windows.Controls; +using RPGPlugin.Utils; +using Torch.Collections; namespace RPGPlugin { public partial class RolesControl : UserControl { private Roles Plugin { get; } - + private Timer _delayLoad = new Timer(TimeSpan.FromSeconds(5).TotalMilliseconds); + private MtObservableCollection, TabItem> views => Roles.Instance.ClassViews; + private RolesControl() { InitializeComponent(); } + private void ClassViewsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + TabItem item = sender as TabItem; + if (item == null) return; + SettingsTab.Items.Add((TabItem) sender); + _delayLoad.Elapsed += DelayLoadOnElapsed; + _delayLoad.Start(); + } + + private void DelayLoadOnElapsed(object sender, ElapsedEventArgs e) + { + _delayLoad.Elapsed -= DelayLoadOnElapsed; + Application.Current.Dispatcher.BeginInvoke((Action)(() => + { + if (views == null || views.Count <= 0) return; + foreach (TabItem view in Roles.Instance.ClassViews) + { + if (view.Header == null ) return; + + SettingsTab.Items.Add(view); + + } + })); + } + public RolesControl(Roles plugin) : this() { Plugin = plugin; @@ -22,10 +55,13 @@ public RolesControl(Roles plugin) : this() BaseSaveLocation.DataContext = plugin.Config; SettingsTab.DataContext = plugin.Config; + Roles.Instance.ClassViews.CollectionChanged += ClassViewsOnCollectionChanged; + // ** These should go to a view for each class at some point. Each view can register in code behind. // RPGPluginControl.xaml can add them in code behind. Create a tab for each registered view and use the view for tabitem content. // Miner Config - ExpRatioDataGrid.DataContext = (MinerConfig)Roles.classConfigs["MinerConfig"]; + /* + ExpRatioDataGrid.DataContext = (MinerConfig)Roles.classConfigs["MinerConfig"]; ExpRatioDataGrid.ItemsSource = Roles.classConfigs["MinerConfig"].ExpRatio; // Warrior Config WarriorDataGrid.DataContext = (WarriorConfig)Roles.classConfigs["WarriorConfig"]; @@ -33,6 +69,7 @@ public RolesControl(Roles plugin) : this() // Hunter Config HunterDataGrid.DataContext = (HunterConfig)Roles.classConfigs["HunterConfig"]; HunterDataGrid.ItemsSource = Roles.classConfigs["HunterConfig"].ExpRatio; + */ } public void Donate_Click(object sender, RoutedEventArgs e) diff --git a/RPGPlugin/Utils/HelperFunctions.cs b/RPGPlugin/Utils/HelperFunctions.cs new file mode 100644 index 0000000..522c5af --- /dev/null +++ b/RPGPlugin/Utils/HelperFunctions.cs @@ -0,0 +1,19 @@ +using System; +using System.Threading; + +namespace RPGPlugin.Utils +{ + public static class StaticHelperFunctions + { + public static void StaThreadWrapper(Action action) + { + Thread t = new Thread(o => + { + action(); + System.Windows.Threading.Dispatcher.Run(); + }); + t.SetApartmentState(ApartmentState.STA); + t.Start(); + } + } +} \ No newline at end of file diff --git a/RPGPlugin/Utils/RPGPluginConfig.cs b/RPGPlugin/Utils/RPGPluginConfig.cs index 3c23609..c385d6a 100644 --- a/RPGPlugin/Utils/RPGPluginConfig.cs +++ b/RPGPlugin/Utils/RPGPluginConfig.cs @@ -19,5 +19,6 @@ public class RPGPluginConfig : ViewModel // ROLE, Description - Registered by the class itself. private List> _registeredRoles = new List>(); public List> RegisteredRoles { get => _registeredRoles; set => SetValue(ref _registeredRoles, value); } + } } diff --git a/RPGPlugin/Utils/RoleManager.cs b/RPGPlugin/Utils/RoleManager.cs index 109cf43..57127e8 100644 --- a/RPGPlugin/Utils/RoleManager.cs +++ b/RPGPlugin/Utils/RoleManager.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Threading.Tasks; using RPGPlugin.PointManagementSystem; namespace RPGPlugin.Utils @@ -12,7 +13,7 @@ namespace RPGPlugin.Utils /// public static class RoleAgent { - public static void LoadAllConfigs() + public static async Task LoadAllConfigs() { Assembly asm = Assembly.GetExecutingAssembly(); IEnumerable types = asm.GetTypes().Where(t => t.IsSubclassOf(typeof(configBase))); @@ -20,14 +21,14 @@ public static void LoadAllConfigs() { if (t.Name == "SampleConfig") continue; configBase instance = (configBase)Activator.CreateInstance(t); - instance.init(); - instance.LoadConfig(); - instance.RegisterClass(); + await instance.init(); + await instance.LoadConfig(); Roles.classConfigs.Add(t.Name, instance); + await instance.RegisterClass(); } } - public static void LoadAllClasses() + public static Task LoadAllClasses() { Assembly asm = Assembly.GetExecutingAssembly(); IEnumerable types = asm.GetTypes().Where(t => t.IsSubclassOf(typeof(ClassesBase))); @@ -38,6 +39,8 @@ public static void LoadAllClasses() instance.init(); Roles.roles.Add(t.Name,instance); } + + return Task.CompletedTask; } public static void OnLoaded() From fa619a7e02a1744c688e3f1d6cee0e1995991259 Mon Sep 17 00:00:00 2001 From: SentorX Date: Fri, 28 Apr 2023 23:05:18 +0200 Subject: [PATCH 2/3] Removed excess loops, asm proccessing, unneeded overhead from useless calls to await, etc --- RPGPlugin.csproj | 1 + RPGPlugin/RPGPlugin.cs | 17 +++--- RPGPlugin/Roles/Behavior/WarriorClass.cs | 49 +++++++--------- RPGPlugin/Roles/Config/HunterConfig.cs | 32 +++++------ RPGPlugin/Roles/Config/MinerConfig.cs | 19 +++---- RPGPlugin/Roles/Config/SampleConfig.cs | 9 +-- RPGPlugin/Roles/Config/WarriorConfig.cs | 23 +++----- RPGPlugin/Roles/Config/configBase.cs | 7 +-- RPGPlugin/Roles/View/HunterView.xaml | 4 +- RPGPlugin/Roles/View/HunterView.xaml.cs | 11 +++- RPGPlugin/Roles/View/ViewBase.cs | 10 ++++ RPGPlugin/Torch GUI/RPGPluginControl.xaml.cs | 59 ++++++++++++-------- RPGPlugin/Utils/RoleManager.cs | 59 ++++++++++++-------- 13 files changed, 156 insertions(+), 144 deletions(-) create mode 100644 RPGPlugin/Roles/View/ViewBase.cs diff --git a/RPGPlugin.csproj b/RPGPlugin.csproj index 98cf4bf..fda273e 100644 --- a/RPGPlugin.csproj +++ b/RPGPlugin.csproj @@ -141,6 +141,7 @@ HunterView.xaml + diff --git a/RPGPlugin/RPGPlugin.cs b/RPGPlugin/RPGPlugin.cs index e347512..a5418cf 100644 --- a/RPGPlugin/RPGPlugin.cs +++ b/RPGPlugin/RPGPlugin.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using System.Timers; using System.Windows.Controls; +using System.Windows.Threading; using System.Xml.Serialization; using RPGPlugin.PointManagementSystem; using Sandbox.Engine.Multiplayer; @@ -20,7 +21,6 @@ using Torch.Session; using VRage.GameServices; using RPGPlugin.Utils; -using Sandbox.Game.Multiplayer; using Torch.Collections; using Timer = System.Timers.Timer; @@ -33,8 +33,9 @@ public class Roles : TorchPluginBase, IWpfPlugin public static ConcurrentDictionary PlayerManagers = new ConcurrentDictionary(); public static Dictionary classConfigs = new Dictionary(); public static Dictionary roles = new Dictionary(); + public MtObservableSortedDictionary classViews = new MtObservableSortedDictionary(); + public readonly Dispatcher MainDispatcher = Dispatcher.CurrentDispatcher; private Timer _delayManagers = new Timer(TimeSpan.FromSeconds(5).TotalMilliseconds); - public MtObservableCollection, TabItem> ClassViews = new MtObservableList(); public PatchManager patchManager; public PatchContext patchContext; public static IChatManagerServer ChatManager => Instance.Torch.CurrentSession.Managers.GetManager(); @@ -52,6 +53,7 @@ public class Roles : TorchPluginBase, IWpfPlugin public override async void Init(ITorchBase torch) { base.Init(torch); + Roles.Log.Warn($"MainPlugin Thread => {Thread.CurrentThread.ManagedThreadId}"); Instance = this; await SetupConfig(); @@ -67,7 +69,7 @@ public override async void Init(ITorchBase torch) patchContext = patchManager.AcquireContext(); DrillPatch.Patch(patchContext); await Save(); - await WaitThenSetupClasses(); + await RoleAgent.LoadAllRoles();; // Give the system time to write and release the saved config file } private void DelayManagersOnElapsed(object sender, ElapsedEventArgs e) @@ -119,8 +121,6 @@ private void SessionChanged(ITorchSession session, TorchSessionState state) private async void PlayerDisconnected(ulong steamID, MyChatMemberStateChangeEnum myChatMemberStateChangeEnum) { // Unload them from the system, free up resources. - MyPlayer player = MySession.Static.Players.TryGetPlayerBySteamId(steamID); - if (!PlayerManagers.ContainsKey(steamID)) { Log.Error($"Unable to save profile for player [SteamID:{steamID}], it was probably not loaded."); @@ -142,7 +142,6 @@ private async void SaveAllPlayersForShutDown() private static void PlayerConnected(ulong steamID, string s) { - long playerId = Sync.Players.TryGetIdentityId(steamID); PlayerManager roleManager = new PlayerManager(); roleManager.InitAsync(steamID); PlayerManagers.TryAdd(steamID, roleManager); @@ -217,14 +216,16 @@ public Task Save() private async Task WaitThenSetupClasses() { + // Had issues were roles were loaded faster than the config was created... causes issues. await Task.Run(async () => { while (Config == null) { + // If the config is null, wait a second and try again. Repeat until config is loaded. Thread.Sleep(1000); } - await RoleAgent.LoadAllConfigs(); - await RoleAgent.LoadAllClasses(); + + await RoleAgent.LoadAllRoles(); }); } diff --git a/RPGPlugin/Roles/Behavior/WarriorClass.cs b/RPGPlugin/Roles/Behavior/WarriorClass.cs index 03af568..d8b703c 100644 --- a/RPGPlugin/Roles/Behavior/WarriorClass.cs +++ b/RPGPlugin/Roles/Behavior/WarriorClass.cs @@ -23,12 +23,10 @@ public class WarriorClass : ClassesBase { /// /// Point to your classConfig ExpRatio collection - public override ObservableCollection> ExpRatio { get; set; } = - new ObservableCollection>(); + public override ObservableCollection> ExpRatio { get; set; } = new ObservableCollection>(); //test skill point system - public override ObservableCollection> SkillPoints { get; set; } = - new ObservableCollection>(); + public override ObservableCollection> SkillPoints { get; set; } = new ObservableCollection>(); /// public override void init() @@ -47,32 +45,25 @@ private void DamageHandler(object target, ref MyDamageInformation info) // Deformation damage can be from ramming such as torpedo grids, or a warship hitting another. // Will do a sample here. Be warned... This requires allot of work and will become a bit long... :) - if (target is MyCubeBlock block) - { - // Get relation between grid and attacker - if (block.IDModule.GetUserRelationToOwner(info.AttackerId) != MyRelationsBetweenPlayerAndBlock.Friends) + if (!(target is MyCubeBlock block)) return; + + // Get relation between grid and attacker + if (block.IDModule.GetUserRelationToOwner(info.AttackerId) == MyRelationsBetweenPlayerAndBlock.Friends) return; + + if (block.CubeGrid.GridSizeEnum == MyCubeSize.Small) + _ProcessQueue.Enqueue(new ExperienceAction { - switch (block.CubeGrid.GridSizeEnum) - { - case MyCubeSize.Small: - _ProcessQueue.Enqueue( new ExperienceAction - { - ownerID = info.AttackerId, - subType = "EnemySmallBlock", - amount = info.Amount // This gives points per point of damage. - }); - break; - case MyCubeSize.Large: - _ProcessQueue.Enqueue( new ExperienceAction - { - ownerID = info.AttackerId, - subType = "EnemyLargeBlock", - amount = info.Amount // This gives points per point of damage. - }); - break; - } - } - } + ownerID = info.AttackerId, + subType = "EnemySmallBlock", + amount = info.Amount // This gives points per point of damage. + }); + else if (block.CubeGrid.GridSizeEnum == MyCubeSize.Large) + _ProcessQueue.Enqueue(new ExperienceAction + { + ownerID = info.AttackerId, + subType = "EnemyLargeBlock", + amount = info.Amount // This gives points per point of damage. + }); } /// diff --git a/RPGPlugin/Roles/Config/HunterConfig.cs b/RPGPlugin/Roles/Config/HunterConfig.cs index 3252ff0..8ff4b7f 100644 --- a/RPGPlugin/Roles/Config/HunterConfig.cs +++ b/RPGPlugin/Roles/Config/HunterConfig.cs @@ -2,13 +2,15 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; +using System.Net.Mime; using System.Threading; using System.Threading.Tasks; +using System.Windows; using System.Windows.Controls; +using System.Windows.Threading; using Newtonsoft.Json; using RPGPlugin.Utils; using RPGPlugin.View; -using static RPGPlugin.Utils.StaticHelperFunctions; namespace RPGPlugin { @@ -23,46 +25,40 @@ public sealed class HunterConfig : configBase public override ObservableCollection> SkillPoints { get; set; } = new ObservableCollection>(); - public override Task init() + public override void init() { // Initialize class with default settings, will be replaced if a config file is loaded. ExpRatio.Add(new KeyValuePair("Wolf", 0.0013 )); ExpRatio.Add(new KeyValuePair("Spider", 0.0013 )); ExpRatio.Add(new KeyValuePair("SmallBlock", 2 )); ExpRatio.Add(new KeyValuePair("LargeBlock", 10 )); - - // Init View - - StaThreadWrapper(() => + + StaticHelperFunctions.StaThreadWrapper(() => { - UserControl view = new HunterView(); - view.Visibility = System.Windows.Visibility.Visible; - TabItem item = new TabItem {Header = "Hunter", Content = view}; - Roles.Instance.ClassViews.Add(item); + Roles.Log.Warn($"HunterSTA Thread => {Thread.CurrentThread.ManagedThreadId}"); + UserControl classView = new Hunter(); + Roles.Instance.classViews.Add("Hunter", classView); + }); - return Task.CompletedTask; } - public override Task RegisterClass() + public override void RegisterClass() { // Register Class Info SerializableTuple RoleToRegister = new SerializableTuple{Item1 = "Hunter", Item2 = "Specialized in attacking NPC ships and creatures."}; - if (Roles.Instance.Config.RegisteredRoles.Any(role => role.Item1.Equals(RoleToRegister.Item1, StringComparison.OrdinalIgnoreCase))) return Task.CompletedTask; + if (Roles.Instance.Config.RegisteredRoles.Any(role => role.Item1.Equals(RoleToRegister.Item1, StringComparison.OrdinalIgnoreCase))) return ; Roles.Instance.Config.RegisteredRoles.Add(RoleToRegister); Roles.Log.Warn($"Registered New Class: {RoleToRegister.Item1}"); - - return Task.CompletedTask; } - public override Task LoadConfig() + public override void LoadConfig() { string data = GetConfig().Result; - if (data == null) return Task.CompletedTask; + if (data == null) return; HunterConfig classConfig = JsonConvert.DeserializeObject(data); ExpRatio = classConfig.ExpRatio; - return Task.CompletedTask; } public override async Task SaveConfig() diff --git a/RPGPlugin/Roles/Config/MinerConfig.cs b/RPGPlugin/Roles/Config/MinerConfig.cs index 8521da9..6184a4d 100644 --- a/RPGPlugin/Roles/Config/MinerConfig.cs +++ b/RPGPlugin/Roles/Config/MinerConfig.cs @@ -13,14 +13,12 @@ public sealed class MinerConfig : configBase // Definition of the ExpRatio property, which stores experience point values for individual minerals /// - public override ObservableCollection> ExpRatio { get; set; } = - new ObservableCollection>(); + public override ObservableCollection> ExpRatio { get; set; } = new ObservableCollection>(); //test skill point system - public override ObservableCollection> SkillPoints { get; set; } = - new ObservableCollection>(); + public override ObservableCollection> SkillPoints { get; set; } = new ObservableCollection>(); - public override Task init() + public override void init() { base.init(); // Set defaults, will be used if no config file has been created or becomes corrupt. @@ -35,29 +33,26 @@ public override Task init() ExpRatio.Add(new KeyValuePair( "Platinum", 0.28 )); ExpRatio.Add(new KeyValuePair( "Uranium", 0.30 )); ExpRatio.Add(new KeyValuePair( "Ice", 0.135 )); - return Task.CompletedTask; } - public override Task RegisterClass() + public override void RegisterClass() { SerializableTuple RoleToRegister = new SerializableTuple{Item1 = "Miner", Item2 = "Specialized in resource extraction."}; - if (Roles.Instance.Config.RegisteredRoles.Any(Role => Role.Item1.Equals(RoleToRegister.Item1, StringComparison.OrdinalIgnoreCase))) return Task.CompletedTask; + if (Roles.Instance.Config.RegisteredRoles.Any(Role => Role.Item1.Equals(RoleToRegister.Item1, StringComparison.OrdinalIgnoreCase))) return; Roles.Instance.Config.RegisteredRoles.Add(RoleToRegister); Roles.Log.Warn($"Registered New Class: {RoleToRegister.Item1}"); - return Task.CompletedTask; } - public override Task LoadConfig() + public override void LoadConfig() { string data = GetConfig().Result; - if (data == null) return Task.CompletedTask; + if (data == null) return; MinerConfig classConfig = JsonConvert.DeserializeObject(data); ExpRatio = classConfig.ExpRatio; - return Task.CompletedTask; } public override async Task SaveConfig() diff --git a/RPGPlugin/Roles/Config/SampleConfig.cs b/RPGPlugin/Roles/Config/SampleConfig.cs index 8850bcc..0d6060b 100644 --- a/RPGPlugin/Roles/Config/SampleConfig.cs +++ b/RPGPlugin/Roles/Config/SampleConfig.cs @@ -15,7 +15,7 @@ public class SampleConfig : configBase public override ObservableCollection> SkillPoints { get; set; } = new ObservableCollection>(); - public override Task init() + public override void init() { // Always run this method first! // base.init(); @@ -23,10 +23,9 @@ public override Task init() // Set your default XP values here, they will load before your config fill // will, and will be used if no config file has been created at this point. // See MinerClass for an example. - return Task.CompletedTask; } - public override Task LoadConfig() + public override void LoadConfig() { // This will load your default settings when called. If none exist you // should create default settings in a new method. @@ -34,7 +33,6 @@ public override Task LoadConfig() // Returns your config file in json format if it exists, null if not. // string data = GetConfig().Result; // if (data == null) return; - return Task.CompletedTask; } public override Task SaveConfig() @@ -48,7 +46,7 @@ public override Task SaveConfig() return Task.CompletedTask; } - public override Task RegisterClass() + public override void RegisterClass() { /* Tuple RoleToRegister = new Tuple("This Is The Class Title", "This Is A Description Of The Class"); @@ -56,7 +54,6 @@ public override Task RegisterClass() if (!Roles.Instance.Config.RegisteredRoles.Contains(RoleToRegister)) Roles.Instance.Config.RegisteredRoles.Add(RoleToRegister); */ - return Task.CompletedTask; } } } \ No newline at end of file diff --git a/RPGPlugin/Roles/Config/WarriorConfig.cs b/RPGPlugin/Roles/Config/WarriorConfig.cs index a70dabe..3e492f6 100644 --- a/RPGPlugin/Roles/Config/WarriorConfig.cs +++ b/RPGPlugin/Roles/Config/WarriorConfig.cs @@ -12,47 +12,38 @@ public sealed class WarriorConfig : configBase { // Definition of the ExpRatio property, which stores experience point values for individual minerals /// - public override ObservableCollection> ExpRatio { get; set; } = - new ObservableCollection>(); + public override ObservableCollection> ExpRatio { get; set; } = new ObservableCollection>(); //test skill point system - public override ObservableCollection> SkillPoints { get; set; } = - new ObservableCollection>(); + public override ObservableCollection> SkillPoints { get; set; } = new ObservableCollection>(); - public override Task init() + public override void init() { // Initialize class with default settings, will be replaced if a config file is loaded. ExpRatio.Add(new KeyValuePair("EnemyPlayer", 25 )); ExpRatio.Add(new KeyValuePair("EnemySmallBlock", 0.2 )); ExpRatio.Add(new KeyValuePair("EnemyLargeBlock", 0.8 )); - // 0 point values can be omitted. If its not in the list, its the same as 0 - // ExpRatio.Add(new KeyValuePair("FriendlySmallBlock", 0 )); - // ExpRatio.Add(new KeyValuePair("FriendlyLargeBlock", 0 )); - //test skill point system SkillPoints.Add(new KeyValuePair(2, 1)); - return Task.CompletedTask; } - public override Task RegisterClass() + public override void RegisterClass() { SerializableTuple RoleToRegister = new SerializableTuple{Item1 = "Warrior", Item2 = "Specialized in battles and destruction of other engineers things!."}; - if (Roles.Instance.Config.RegisteredRoles.Any(Role => Role.Item1.Equals(RoleToRegister.Item1, StringComparison.OrdinalIgnoreCase))) return Task.CompletedTask; + if (Roles.Instance.Config.RegisteredRoles.Any(Role => Role.Item1.Equals(RoleToRegister.Item1, StringComparison.OrdinalIgnoreCase))) return; Roles.Instance.Config.RegisteredRoles.Add(RoleToRegister); Roles.Log.Warn($"Registered New Class: {RoleToRegister.Item1}"); - return Task.CompletedTask; } - public override Task LoadConfig() + public override void LoadConfig() { string data = GetConfig().Result; - if (data == null) return Task.CompletedTask; + if (data == null) return; WarriorConfig classConfig = JsonConvert.DeserializeObject(data); ExpRatio = classConfig.ExpRatio; - return Task.CompletedTask; } public override async Task SaveConfig() diff --git a/RPGPlugin/Roles/Config/configBase.cs b/RPGPlugin/Roles/Config/configBase.cs index 693a733..7268841 100644 --- a/RPGPlugin/Roles/Config/configBase.cs +++ b/RPGPlugin/Roles/Config/configBase.cs @@ -29,15 +29,14 @@ public abstract class configBase /// /// Initializer, always start with base.int(). This sets the config file save location and name. /// - public virtual Task init() + public virtual void init() { - return Task.CompletedTask; } /// /// Register the class type in the master list! /// - public abstract Task RegisterClass(); + public abstract void RegisterClass(); protected virtual string GetFileName() { @@ -48,7 +47,7 @@ protected virtual string GetFileName() /// /// GetConfig().Results returns your your config data as json. /// - public abstract Task LoadConfig(); + public abstract void LoadConfig(); /// /// The following SHOULD work in most cases: diff --git a/RPGPlugin/Roles/View/HunterView.xaml b/RPGPlugin/Roles/View/HunterView.xaml index 56f50d7..f52bf97 100644 --- a/RPGPlugin/Roles/View/HunterView.xaml +++ b/RPGPlugin/Roles/View/HunterView.xaml @@ -1,4 +1,4 @@ - - + Test diff --git a/RPGPlugin/Roles/View/HunterView.xaml.cs b/RPGPlugin/Roles/View/HunterView.xaml.cs index c79e8ac..8c6aa9d 100644 --- a/RPGPlugin/Roles/View/HunterView.xaml.cs +++ b/RPGPlugin/Roles/View/HunterView.xaml.cs @@ -1,12 +1,19 @@ +using System.Threading; using System.Windows.Controls; namespace RPGPlugin.View { - public partial class HunterView : UserControl + public partial class Hunter : UserControl, ViewBase { - public HunterView() + public Hunter() { InitializeComponent(); } + + + public void LogThread() + { + Roles.Log.Warn($"HunterView Thread => {Thread.CurrentThread.ManagedThreadId}"); + } } } \ No newline at end of file diff --git a/RPGPlugin/Roles/View/ViewBase.cs b/RPGPlugin/Roles/View/ViewBase.cs new file mode 100644 index 0000000..7eb52c7 --- /dev/null +++ b/RPGPlugin/Roles/View/ViewBase.cs @@ -0,0 +1,10 @@ +using System.Windows.Controls; + +namespace RPGPlugin.View +{ + public interface ViewBase + { + void LogThread(); + + } +} \ No newline at end of file diff --git a/RPGPlugin/Torch GUI/RPGPluginControl.xaml.cs b/RPGPlugin/Torch GUI/RPGPluginControl.xaml.cs index 728ddfb..be018e4 100644 --- a/RPGPlugin/Torch GUI/RPGPluginControl.xaml.cs +++ b/RPGPlugin/Torch GUI/RPGPluginControl.xaml.cs @@ -1,51 +1,61 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; using System.Diagnostics; -using System.Net.Mime; +using System.Threading; +using System.Threading.Tasks; using System.Timers; using System.Windows; using System.Windows.Controls; +using NLog; using RPGPlugin.Utils; -using Torch.Collections; +using Timer = System.Timers.Timer; namespace RPGPlugin { public partial class RolesControl : UserControl { private Roles Plugin { get; } - private Timer _delayLoad = new Timer(TimeSpan.FromSeconds(5).TotalMilliseconds); - private MtObservableCollection, TabItem> views => Roles.Instance.ClassViews; + private Timer _delayLoad = new Timer(TimeSpan.FromSeconds(3).TotalMilliseconds); private RolesControl() { InitializeComponent(); } - private void ClassViewsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + private void DelayLoadOnElapsed(object sender, ElapsedEventArgs e) { - TabItem item = sender as TabItem; - if (item == null) return; - SettingsTab.Items.Add((TabItem) sender); - _delayLoad.Elapsed += DelayLoadOnElapsed; - _delayLoad.Start(); + + DelayAsyncWorker(sender, e); + } - private void DelayLoadOnElapsed(object sender, ElapsedEventArgs e) + private Task DelayAsyncWorker(object sender, ElapsedEventArgs e) { + Roles.Log.Warn($"Timer Thread => {Thread.CurrentThread.ManagedThreadId}"); _delayLoad.Elapsed -= DelayLoadOnElapsed; - Application.Current.Dispatcher.BeginInvoke((Action)(() => + + foreach (KeyValuePair classView in Roles.Instance.classViews) { - if (views == null || views.Count <= 0) return; - foreach (TabItem view in Roles.Instance.ClassViews) + Roles.Instance.MainDispatcher.Invoke(() => // Were on the timer thread, method needs to run on UI thread. { - if (view.Header == null ) return; - - SettingsTab.Items.Add(view); - - } - })); + Helper(classView); + }); + + } + + return Task.CompletedTask; + } + + private void Helper(KeyValuePair classView) + { + TabItem newView = new TabItem + { + Header = classView.Key, + Content = classView.Value + }; + + Roles.Log.Warn("Adding TabItem to SettingsTab."); + SettingsTab.Items.Add(newView); } public RolesControl(Roles plugin) : this() @@ -54,8 +64,9 @@ public RolesControl(Roles plugin) : this() DataContext = this; BaseSaveLocation.DataContext = plugin.Config; SettingsTab.DataContext = plugin.Config; - - Roles.Instance.ClassViews.CollectionChanged += ClassViewsOnCollectionChanged; + _delayLoad.Elapsed += DelayLoadOnElapsed; + _delayLoad.Start(); + Roles.Log.Warn($"Main View Thread => {Thread.CurrentThread.ManagedThreadId}"); // ** These should go to a view for each class at some point. Each view can register in code behind. // RPGPluginControl.xaml can add them in code behind. Create a tab for each registered view and use the view for tabitem content. diff --git a/RPGPlugin/Utils/RoleManager.cs b/RPGPlugin/Utils/RoleManager.cs index 57127e8..e2289fa 100644 --- a/RPGPlugin/Utils/RoleManager.cs +++ b/RPGPlugin/Utils/RoleManager.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; +using System.Threading; using System.Threading.Tasks; using RPGPlugin.PointManagementSystem; @@ -13,33 +13,46 @@ namespace RPGPlugin.Utils /// public static class RoleAgent { - public static async Task LoadAllConfigs() + // Increase load performance by putting this all in one single search through the assembly. + // instead of searching through the assembly for one type, than searching again for the next... + // Removed LINQ cause that's slow as hell, use reverse for loop is very fast and efficient. + + private static Assembly asm = Assembly.GetExecutingAssembly(); + + public static Task LoadAllRoles() { - Assembly asm = Assembly.GetExecutingAssembly(); - IEnumerable types = asm.GetTypes().Where(t => t.IsSubclassOf(typeof(configBase))); - foreach (Type t in types) + Roles.Log.Warn($"RoleManager Thread => {Thread.CurrentThread.ManagedThreadId}"); + Type[] types = asm.GetTypes(); + for (int index = types.Length - 1; index >= 0; index--) { - if (t.Name == "SampleConfig") continue; - configBase instance = (configBase)Activator.CreateInstance(t); - await instance.init(); - await instance.LoadConfig(); - Roles.classConfigs.Add(t.Name, instance); - await instance.RegisterClass(); + if (types[index].IsSubclassOf(typeof(configBase))) + { + if (types[index].Name == "SampleConfig") continue; + configBase instance = (configBase) Activator.CreateInstance(types[index]); + Roles.classConfigs.Add(types[index].Name, instance); + } + + if (types[index].IsSubclassOf(typeof(ClassesBase))) + { + if (types[index].Name == "SampleClass") continue; + ClassesBase instance = (ClassesBase) Activator.CreateInstance(types[index]); + Roles.roles.Add(types[index].Name, instance); + } } - } - - public static Task LoadAllClasses() - { - Assembly asm = Assembly.GetExecutingAssembly(); - IEnumerable types = asm.GetTypes().Where(t => t.IsSubclassOf(typeof(ClassesBase))); - foreach (Type t in types) + + foreach (KeyValuePair config in Roles.classConfigs) { - if (t.Name == "SampleClass") continue; - ClassesBase instance = (ClassesBase)Activator.CreateInstance(t); - instance.init(); - Roles.roles.Add(t.Name,instance); + config.Value.init(); + config.Value.LoadConfig(); + config.Value.RegisterClass(); } - + + foreach (KeyValuePair role in Roles.roles) + { + role.Value.init(); + } + + asm = null; return Task.CompletedTask; } From dbc8e95b63c3a491ac4e3b0260279ab34fc516c5 Mon Sep 17 00:00:00 2001 From: SentorX Date: Sat, 29 Apr 2023 00:36:18 +0200 Subject: [PATCH 3/3] All class now have their own fully functioning views. These are auto loaded with no extra work as long as the designer of the classes follows the requirements for their behavior, config, and view file. The plugin will do the rest. --- RPGPlugin.csproj | 19 +- RPGPlugin/Roles/Config/HunterConfig.cs | 7 +- RPGPlugin/Roles/Config/MinerConfig.cs | 3 + RPGPlugin/Roles/Config/SampleConfig.cs | 3 + RPGPlugin/Roles/Config/WarriorConfig.cs | 5 + RPGPlugin/Roles/View/Hunter.xaml | 92 ++++++ RPGPlugin/Roles/View/Hunter.xaml.cs | 100 ++++++ RPGPlugin/Roles/View/HunterView.xaml | 12 - RPGPlugin/Roles/View/HunterView.xaml.cs | 19 -- RPGPlugin/Roles/View/Miner.xaml | 96 ++++++ RPGPlugin/Roles/View/Miner.xaml.cs | 98 ++++++ RPGPlugin/Roles/View/ViewBase.cs | 10 - RPGPlugin/Roles/View/Warrior.xaml | 93 ++++++ RPGPlugin/Roles/View/Warrior.xaml.cs | 98 ++++++ .../{Behavior => baseClasses}/ClassesBase.cs | 0 .../{Config => baseClasses}/configBase.cs | 5 + RPGPlugin/Torch GUI/RPGPluginControl.xaml | 57 ---- RPGPlugin/Torch GUI/RPGPluginControl.xaml.cs | 308 +----------------- RPGPlugin/Utils/RoleManager.cs | 29 +- 19 files changed, 642 insertions(+), 412 deletions(-) create mode 100644 RPGPlugin/Roles/View/Hunter.xaml create mode 100644 RPGPlugin/Roles/View/Hunter.xaml.cs delete mode 100644 RPGPlugin/Roles/View/HunterView.xaml delete mode 100644 RPGPlugin/Roles/View/HunterView.xaml.cs create mode 100644 RPGPlugin/Roles/View/Miner.xaml create mode 100644 RPGPlugin/Roles/View/Miner.xaml.cs delete mode 100644 RPGPlugin/Roles/View/ViewBase.cs create mode 100644 RPGPlugin/Roles/View/Warrior.xaml create mode 100644 RPGPlugin/Roles/View/Warrior.xaml.cs rename RPGPlugin/Roles/{Behavior => baseClasses}/ClassesBase.cs (100%) rename RPGPlugin/Roles/{Config => baseClasses}/configBase.cs (96%) diff --git a/RPGPlugin.csproj b/RPGPlugin.csproj index fda273e..c519f67 100644 --- a/RPGPlugin.csproj +++ b/RPGPlugin.csproj @@ -127,21 +127,26 @@ Settings.settings True - + + - - - HunterView.xaml + + Hunter.xaml + + + Miner.xaml + + + Warrior.xaml - @@ -184,7 +189,9 @@ Designer MSBuild:Compile - + + + MSBuild:Compile Designer diff --git a/RPGPlugin/Roles/Config/HunterConfig.cs b/RPGPlugin/Roles/Config/HunterConfig.cs index 8ff4b7f..cdbdc7d 100644 --- a/RPGPlugin/Roles/Config/HunterConfig.cs +++ b/RPGPlugin/Roles/Config/HunterConfig.cs @@ -2,12 +2,9 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using System.Net.Mime; using System.Threading; using System.Threading.Tasks; -using System.Windows; using System.Windows.Controls; -using System.Windows.Threading; using Newtonsoft.Json; using RPGPlugin.Utils; using RPGPlugin.View; @@ -17,6 +14,10 @@ namespace RPGPlugin public sealed class HunterConfig : configBase { // Definition of the ExpRatio property, which stores experience point values for individual minerals + + /// + public override string ViewName { get; } = "Hunter"; + /// public override ObservableCollection> ExpRatio { get; set; } = new ObservableCollection>(); diff --git a/RPGPlugin/Roles/Config/MinerConfig.cs b/RPGPlugin/Roles/Config/MinerConfig.cs index 6184a4d..5f2fb09 100644 --- a/RPGPlugin/Roles/Config/MinerConfig.cs +++ b/RPGPlugin/Roles/Config/MinerConfig.cs @@ -12,6 +12,9 @@ public sealed class MinerConfig : configBase { // Definition of the ExpRatio property, which stores experience point values for individual minerals + /// + public override string ViewName { get; } = "Miner"; + /// public override ObservableCollection> ExpRatio { get; set; } = new ObservableCollection>(); diff --git a/RPGPlugin/Roles/Config/SampleConfig.cs b/RPGPlugin/Roles/Config/SampleConfig.cs index 0d6060b..1f604e5 100644 --- a/RPGPlugin/Roles/Config/SampleConfig.cs +++ b/RPGPlugin/Roles/Config/SampleConfig.cs @@ -15,6 +15,9 @@ public class SampleConfig : configBase public override ObservableCollection> SkillPoints { get; set; } = new ObservableCollection>(); + /// + public override string ViewName { get; } = "Sample"; + public override void init() { // Always run this method first! diff --git a/RPGPlugin/Roles/Config/WarriorConfig.cs b/RPGPlugin/Roles/Config/WarriorConfig.cs index 3e492f6..e2573c6 100644 --- a/RPGPlugin/Roles/Config/WarriorConfig.cs +++ b/RPGPlugin/Roles/Config/WarriorConfig.cs @@ -11,12 +11,17 @@ namespace RPGPlugin public sealed class WarriorConfig : configBase { // Definition of the ExpRatio property, which stores experience point values for individual minerals + + /// public override ObservableCollection> ExpRatio { get; set; } = new ObservableCollection>(); //test skill point system public override ObservableCollection> SkillPoints { get; set; } = new ObservableCollection>(); + /// + public override string ViewName { get; } = "Warrior"; + public override void init() { // Initialize class with default settings, will be replaced if a config file is loaded. diff --git a/RPGPlugin/Roles/View/Hunter.xaml b/RPGPlugin/Roles/View/Hunter.xaml new file mode 100644 index 0000000..35ca962 --- /dev/null +++ b/RPGPlugin/Roles/View/Hunter.xaml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +