Git Product home page Git Product logo

bannerlord.mboptionscreen's Introduction

bannerlord.mboptionscreen's People

Contributors

aragas avatar codefactor-io[bot] avatar dependabot[bot] avatar gedevan-aleksizde avatar github-actions[bot] avatar mipen avatar reaperanon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

bannerlord.mboptionscreen's Issues

Installing from NuGet, v2 api SettingPropertyBoolAttribute is internal and could not be accessed from CustomSetting class

When I am trying to set up a configuration like in the wiki.

[SettingPropertyBool(displayName: "Setting Name", order: 0, requireRestart: false, hintText: "Setting explanation.")]

It got a popup saying that SettingPropertyBoolAttribute is an internal class.

Cannot access the internal class here.

I am using MBOptionScreen 1.1.15 installed from NuGet.

I use my JetBrain Rider to decompile SettingPropertyBoolAttribute . It says

namespace MBOptionScreen.Attributes
{
  [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
  internal class SettingPropertyBoolAttribute : BaseSettingPropertyAttribute
  {
    public SettingPropertyBoolAttribute(
      string displayName,
      int order = -1,
      bool requireRestart = true,
      string hintText = "")
      : base(displayName, order, requireRestart, hintText)
    {
    }
  }
}

Actually an internal class from my end

Enumerating all types in all assemblies breaks dynamically managed references

I'm the author of https://github.com/int19h/Bannerlord.CSharp.Scripting, and I've had some user reports regarding its incompatibilities with MCM. I have investigated it, and I think this is something that needs to be fixed on MCM side.

The MCM code in question is this:

var allTypes = AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => !a.IsDynamic)
.SelectMany(a => a.GetTypes())
.Where(t => t.IsClass && !t.IsAbstract && t.GetConstructor(Type.EmptyTypes) is not null)
.ToList();

And specifically, the part that calls GetTypes() on every loaded assembly. It might sound weird - certainly was weird to me! - but, apparently, this is not a safe operation on just any random assembly.

The reason is that some assemblies have references to other assemblies that might not always be there at runtime, and rely on .NET rules for when types get loaded (i.e. on first reference, not on assembly load) to ensure that such types are not loaded when the reference isn't there. The specific case that me and my users are hitting is Roslyn, which uses System.Runtime.Loader on .NET Core/5, and Assembly.Load etc otherwise. They implement this by having different classes for each, and dynamically instantiating one or the other depending on the platform:

https://github.com/dotnet/roslyn/blob/315c2e149ba7889b0937d872274c33fcbfe9af5f/src/Scripting/Core/Hosting/AssemblyLoader/AssemblyLoaderImpl.cs#L24-L41

That is, CoreAssemblyLoaderImpl is the class that only works on Core/5, and will cause an exception otherwise - but in normal Roslyn operation, it just never gets loaded when running on desktop CLR, and thus everything is fine.

But when MCM calls GetTypes() on Microsoft.CodeAnalysis.Scripting assembly, it forces all types in the assembly to be loaded regardless - and that load then causes a missing assembly exception for System.Runtime.Loader, which is uncaught, and thus crashes the game.

I believe the technique used by Roslyn is valid - CLR delayed loading for types is well-specified for this reason, among others. So the fix should be on the GetTypes() side of things. Specifically, it cannot assume that GetTypes() is exception-free (indeed, it is is documented to not be). The easiest fix would be for the loop to wrap GetTypes() in a try-catch for ReflectionTypeLoadException, and simply ignore any assembly that causes it.

Mod does not show up in list after starting new campaign

Hi, as you may know I've converted BannerlordCheats to use PerSaveSettings.
Everything works great except that when starting a new campaign the mod does not show up in the MCM list until after saving, exiting to menu and loading the save again. Could you take a look at that?
Cheers

MCM Documentation

  • Document MCM Interfaces
  • Add inheritdocs in MCM
  • Document MCM
  • Document MCM.UI
  • Link against Bannerlord API

Game becomes unpaused when entering options screen

Hi there,
I noticed that when entering the options screen via the escape menu, the game becomes unpaused in the background.
This is problematic for my mod because it is common for users to change its settings during combat encounters.
Could you make it so the game stays paused when the options screen is open?
Thanks and keep up the great work!

[Proton/Linux] Infinite loading on startup

Hi @Aragas,

Just tried Bannerlord on Linux using Proton 6.3-5. Performance is good and I got Harmony, ButterLib and UIExtenderEx running just fine. Once I enable Mod Configuration Menu (tested with v4.3.13.276411) the game is no longer starting up. It's stuck on the following screen, with the horse infinitly animated. Do you have a guess what could cause this?

image

Tested with:
image

Test Badge

There is no way to get the current branch name in the README file, so a workaround would be to introduce two badges - one for master and one for the current dev branch - v3
Use shields.io to make a custom badge name - 'Tests master' and 'Tests v3'

Solved

My Setting class extended correctly as wiki direction but setting not save/load in next open game.

namespace FactionAndBlade.Settings
{
    internal sealed partial class Setting
    {
        private const string Strings = "strings";
        private const string Text_ModName = "{=FactionAndBlade_TextModName}Faction And Blade",

            Text_General_Setting = "General Settings",
            Text_General_EnableDebugMode_Name = "{=FactionAndBlade_General_EnableDebugModeName}Enable debug output",
            Text_General_EnableDebugMode_Hint = "{=FactionAndBlade_General_EnableDebugModeHint}Enable SubModule debug output",

            Text_Faction_Setting = "Faction Settings",
            Text_Faction_Characterstic_EnableCharacterstic_Name = "{=FactionAndBlade_Faction_EnableCharactersticName}Enable faction characteristic",
            Text_Faction_Characterstic_EnableCharacterstic_Hint = "{=FactionAndBlade_Faction_EnableCharactersticHint}Enable faction members can appply faction specialities",

            Text_Faction_Relationship_Setting = "Faction Settings/Relationship Settings",
            Text_Faction_Relationship_EnableRelationship_Name = "{=FactionAndBlade_Faction_Relationship_EnableRelationshipName}Enable faction relationship",
            Text_Faction_Relationship_EnableRelationship_Hint = "{=FactionAndBlade_Faction_Relationship_EnableRelationshipHint}Enable fation members can apply relationship",
            Text_Faction_Relationship_ValueQuitFaction_Name = "{=FactionAndBlade_Faction_Relationship_ValueQuitFactionName}Value quit faction",
            Text_Faction_Relationship_ValueQuitFaction_Hint = "{=FactionAndBlade_Faction_Relationship_ValueQuitFactionHint}Set the value for relation change between leaving member and faction members",
            Text_Faction_Relationship_ValueJoinFaction_Name = "{=FactionAndBlade_Faction_Relationship_ValueJoinFactionName}Value join faction",
            Text_Faction_Relationship_ValueJoinFaction_Hint = "{=FactionAndBlade_Faction_Relationship_ValueJoinFactionHint}Set the value for relation change between new join member and faction members",


            Text_Faction_Characterstic_Setting = "Faction Settings/Characteristic Settings",

            Text_Faction_Characterstic_DemagogueTroop_Setting = "Faction Settings/Characteristic Settings/DemagogueTroops",
            Text_Faction_Characterstic_DemagogueTroop_EnableDemagogueTroop_Name = "{=FactionAndBlade_Faction_Characteristic_DemagogueTroop_EnableDemagogueTroopName}Enable DemagogueTroop",
            Text_Faction_Characterstic_DemagogueTroop_EnableDemagogueTroop_Hint = "{=FactionAndBlade_Faction_Characteristic_DemagogueTroop_EnableDemagogueTroopHint}Enable faction characteristic of DemagogueTroop",

            CharacDemagogueTroopDescr = "={FactionAndBlade_DamagogueTroopDescr}The troops of the faction are under the banner of saving the lives;" +
            "The troops of faction can accept all the refugeee troops;Increase troop maximum size (TroopLeaderFatorCharmLevel * CharmFactor)",
            Text_Faction_Characterstic_CharacDamagogueTroop_FactorCharmName_Name = "{=FactionAndBlade_Faction_Characteristic_DemagogueTroop_FactorCharmName}Factor charm skill",
            Text_Faction_Characterstic_CharacDamagogueTroop_FactorCharmName_Hint = "{=FactionAndBlade_Faction_Characteristic_DemagogueTroop_FactorCharmHint}Set the value of troop leader's skill 'Charm', (Value * SkillLevel) effects the maxiumum troop number",


            Text_RevoltModel_Setting = "RevoltModel Settings",
            Text_RevoltModel_EnableRevoltModel_Name = "{=FactionAndBlade_General_EnableRevolModelName}Enable revolt model",
            Text_RevoltModel_EnableRevoltModel_Hint = "{=FactionAndBlade_General_EnableRevolModelHint}Enable model NPCs will revol governor",
            Text_RevoltModel_FactorRevolChance_Name = "{=FactionAndBlade_RevolModel_FactorChanceName}Factor basic revolt chance",
            Text_RevoltModel_FactorRevolChance_Hint = "{=FactionAndBlade_RevolModel_FactorChanceHint}Set the value for basic chance for hero revol",

            Text_RevoltModel_Spouse_Setting = "RevoltModel Settings/Spouses",
            Text_RevoltModel_SpouseAgeSetting_ValueSpouseAge_Name = "{=FactionAndBlade_RevoltModel_Spouses_ValueUnmarriedAgeName}Value unmarried age",
            Text_RevoltModel_SpouseAgeSetting_ValueSpouseAge_Hint = "{=FactionAndBlade_RevoltModel_Spouses_ValueUnmarriedAgeHint}Set the value of hero spouse age line",


            Text_RevoltModel_Factor_Setting = "RevoltModel Settings/Factor Settings",
            Text_RevoltModel_Factor_EnableFactorSetting_Name = "{=FactionAndBlade_RevoltModel_Factor_EnableFactorSettingName}Enable factor setting",
            Text_RevoltModel_Factor_EnableFactorSetting_Hint = "{=FactionAndBlade_RevoltModel_Factor_EnableFactorSettingHint}Enable factor setting effects the chance of hero revolt",
            Text_RevoltModel_Factor_FactorPositiveChance_Name = "{=FactionAndBlade_RevoltModel_Factor_FactorPositiveChanceName}Factor positive chance",
            Text_RevoltModel_Factor_FactorPositiveChance_Hint = "{=FactionAndBlade_RevoltModel_Factor_FactorPositiveChanceHint}Factor Positive chance",
            Text_RevoltModel_Factor_FactorNegativeChance_Name = "{=FactionAndBlade_RevoltModel_Factor_FactorNegativeChanceName}Factor negative chance",
            Text_RevoltModel_Factor_FactorNegativeChance_Hint = "{=FactionAndBlade_RevoltModel_Factor_FactorNegativeChanceHint}Positive chance",


            Text_RevoltModel_Factor_TraitsSetting = "RevoltModel Settings/Factor Settings/Traits",
            Text_RevoltModel_Factor_Traits_FactorMercy_Name = "{=FactionAndBlade_RevoltModel_Factor_Traits_FactorMercyName}Factor mercy",
            Text_RevoltModel_Factor_Traits_FactorMercy_Hint = "{=FactionAndBlade_RevoltModel_Factor_Traits_FactorMercyHint}Set the value of factor for Mercy",
            Text_RevoltModel_Factor_Traits_FactorValor_Name = "{=FactionAndBlade_RevoltModel_Factor_Traits_FactorValorName}Factor valor",
            Text_RevoltModel_Factor_Traits_FactorValor_Hint = "{=FactionAndBlade_RevoltModel_Factor_Traits_FactorValorHint}Set the value of factor for Valor",
            Text_RevoltModel_Factor_Traits_FactorHonor_Name = "{=FactionAndBlade_RevoltModel_Factor_Traits_FactorHonorName}Factor honor",
            Text_RevoltModel_Factor_Traits_FactorHonor_Hint = "{=FactionAndBlade_RevoltModel_Factor_Traits_FactorHonorHint}Set the value of factor for Honor",
            Text_RevoltModel_Factor_Traits_FactorGenerosity_Name = "{=FactionAndBlade_RevoltModel_Factor_Traits_FactorGenerosityName}Factor generosity",
            Text_RevoltModel_Factor_Traits_FactorGenerosity_Hint = "{=FactionAndBlade_RevoltModel_Factor_Traits_FactorGenerosityHint}Set the value of factor for Generosity",
            Text_RevoltModel_Factor_Traits_FactorCaculation_Name = "{=FactionAndBlade_RevoltModel_Factor_Traits_FactorCaculationName}Factor caculation",
            Text_RevoltModel_Factor_Traits_FactorCaculation_Hint = "{=FactionAndBlade_RevoltModel_Factor_Traits_FactorCaculationHint}Set the value of factor for Caculation",

            Text_RevoltModel_Factor_RelationshipsSetting = "RevoltModel Settings/Factor Settings/Relationships",
            Text_RevoltModel_Factor_Relationships_FactorRelation_Name = "{=FactionAndBlade_RevoltModel_Factor_Relationships_FactorRelationName}Factor relation",
            Text_RevoltModel_Factor_Relationships_FactorRelation_Hint = "{=FactionAndBlade_RevoltModel_Factor_Relationships_FactorRelationHint}Set the value of factor for relation effects revol chance between Govornor and Hero",
            Text_RevoltModel_Factor_Relationships_FactorInform_Name = "{=FactionAndBlade_RevoltModel_Factor_Relationships_FactorInformName}Factor inform",
            Text_RevoltModel_Factor_Relationships_FactorInform_Hint = "{=FactionAndBlade_RevoltModel_Factor_Relationships_FactorInformHint}Set the value of factor for relation change when hero inform revol faction to governor",

            Text_RevoltModel_Factor_Spouses_Setting = "RevoltModel Settings/Factor Settings/Spouses",
            Text_RevoltModel_Factor_Spouses_FactorMarried_Name = "{=FactionAndBlade_RevoltModel_Factor_Spouses_FactorMarriedName}Factor married",
            Text_RevoltModel_Factor_Spouses_FactorMarried_Hint = "{=FactionAndBlade_RevoltModel_Factor_Spouses_FactorMarriedHinnt}Set the value of factor effects chance of revol",
            Text_RevoltModel_Factor_Spouses_FactorSingleOverAge_Name = "{=FactionAndBlade_RevoltModel_Factor_Spouses_FactorSingleOverAgeName}Factor single over age",
            Text_RevoltModel_Factor_Spouses_FactorSingleOverAge_Hint = "{=FactionAndBlade_RevoltModel_Factor_Spouses_FactorSingleOverAgeHint}Set the value of factor for age effects the caucalation",
            Text_RevoltModel_Factor_Spouses_FactorSingleUnderAge_Name = "{=FactionAndBlade_RevoltModel_Factor_Spouses_FactorSingleUnderAgeName}Factor single under age",
            Text_RevoltModel_Factor_Spouses_FactorSingleUnderAge_Hint = "{=FactionAndBlade_RevoltModel_Factor_Spouses_FactorSingleUnderAgerHint}Set the value of factor effects chance of revol",

            Text_RevoltModel_Factor_Others_Setting = "RevoltModel Settings/Factor Settings/Others",
            Text_RevoltModel_Factor_Others_FactorRenown_Name = "{=FactionAndBlade_RevoltModel_Factor_Others_FactorRenownName}Factor renown",
            Text_RevoltModel_Factor_Others_FactorRenown_Hint = "{=FactionAndBlade_RevoltModel_Factor_Others_FactorRenownHint}Set the value of factor effects renown",
            Text_RevoltModel_Factor_Others_FactorAmbition_Name = "{=FactionAndBlade_RevoltModel_Factor_Others_FactorAmbitionName}Factor ambition",
            Text_RevoltModel_Factor_Others_FactorAmbition_Hint = "{=FactionAndBlade_RevoltModel_Factor_Others_FactorAmbitionHint}Set the value of factor effects ambition";

        //private static readonly TextObject ModNameTextObject = new TextObject(Text_ModName);
    }
}
using MBOptionScreen.Attributes;
using MBOptionScreen.Attributes.v2;
using MBOptionScreen.Settings;
using System.Xml;
using System.Xml.Serialization;

namespace FactionAndBlade.Settings
{
    internal sealed partial class Setting : AttributeSettings<Setting>
    {
        public override string ModuleFolderName => SubModuel.ModuleFolderName;
        public override string ModName => $"{SubModuel.Info.Name} {SubModuel.Info.Version}";
        public override string Id { get; set; } = "FactionAndBladeSetting_v2";
        public override string Format => "xml";

        #region ModelSetting

        [XmlElement]
        [SettingPropertyBool(Text_General_EnableDebugMode_Name, HintText = Text_General_EnableDebugMode_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_General_Setting)]
        public bool EnableDebugMode { get; set; } = false;

        #region Faction


        #region Characteristic

        [XmlElement]
        [SettingPropertyBool(Text_Faction_Characterstic_EnableCharacterstic_Name, HintText = Text_Faction_Characterstic_EnableCharacterstic_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_Faction_Characterstic_Setting, IsMainToggle = true)]
        public bool EnableCharacterstic { get; set; } = true;

        #region DemagogueTroopFactor

        [XmlElement]
        [SettingPropertyFloatingInteger(Text_Faction_Characterstic_DemagogueTroop_EnableDemagogueTroop_Name, 0f, 3f, HintText = Text_Faction_Characterstic_DemagogueTroop_EnableDemagogueTroop_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_Faction_Characterstic_DemagogueTroop_Setting,IsMainToggle = true)]
        public bool EnableDemagogueTroop { get; set; } = true;

        [XmlElement]
        [SettingPropertyFloatingInteger(Text_Faction_Characterstic_CharacDamagogueTroop_FactorCharmName_Name, 0f, 3f, HintText = Text_Faction_Characterstic_CharacDamagogueTroop_FactorCharmName_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_Faction_Characterstic_DemagogueTroop_Setting)]
        public float FactorCharm { get; set; } = 0.31F;
        #endregion

        #endregion

        #region Relationship Setting

        [XmlElement]
        [SettingPropertyBool(Text_Faction_Relationship_EnableRelationship_Name, HintText = Text_Faction_Relationship_EnableRelationship_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_Faction_Relationship_Setting,IsMainToggle = true)]
        public bool EnableRelation { get; set; } = true;

        [XmlElement]
        [SettingPropertyIntegerAttribute(Text_Faction_Relationship_ValueQuitFaction_Name, 0, 100, HintText = Text_Faction_Relationship_ValueQuitFaction_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_Faction_Relationship_Setting)]
        public int ValueQuitFaction { get; set; } = 15;
        [XmlElement]
        [SettingPropertyIntegerAttribute(Text_Faction_Relationship_ValueJoinFaction_Name, 0, 100, HintText = Text_Faction_Relationship_ValueJoinFaction_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_Faction_Relationship_Setting)]
        public int ValueFactionRelationJoin { get; set; } = 15;

        #endregion

        #endregion

        #region RevolModel

        [XmlElement]
        [SettingPropertyBool(Text_RevoltModel_EnableRevoltModel_Name, HintText = Text_RevoltModel_EnableRevoltModel_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Setting, IsMainToggle = true)]
        public bool EnableRevoltModel { get; set; } = true;

        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_FactorRevolChance_Name, 0f, 1f, HintText = Text_RevoltModel_FactorRevolChance_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Setting)]
        public float FactorRevolChance { get; set; } = 0.01F;

        #region AgeSetting

        [XmlElement]
        [SettingPropertyIntegerAttribute(Text_RevoltModel_SpouseAgeSetting_ValueSpouseAge_Name, 0, 100, HintText = Text_RevoltModel_SpouseAgeSetting_ValueSpouseAge_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Spouse_Setting)]
        public int ValueSpouseAge { get; set; } = 30;

        #endregion

        #region FactorSetting

        [XmlElement]
        [SettingPropertyBool(Text_RevoltModel_Factor_EnableFactorSetting_Name, HintText = Text_RevoltModel_Factor_EnableFactorSetting_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_Setting, IsMainToggle = true)]
        public bool EnableFactorSetting { get; set; } = true;

        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_Factor_FactorPositiveChance_Name, 0f, 3f, HintText = Text_RevoltModel_Factor_FactorPositiveChance_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_Setting)]
        public float FactorChanceNegative { get; set; } = 0.31F;

        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_Factor_FactorNegativeChance_Name, 0f, 3f, HintText = Text_RevoltModel_Factor_FactorNegativeChance_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_Setting)]
        public float FactorChancePositive { get; set; } = 0.31F;

        #region TraitFactor

        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_Factor_Traits_FactorMercy_Name, 0f, 3f, HintText = Text_RevoltModel_Factor_Traits_FactorMercy_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_TraitsSetting)]
        public float FactorMercy { get; set; } = 0.31F;
        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_Factor_Traits_FactorValor_Name, 0f, 3f, HintText = Text_RevoltModel_Factor_Traits_FactorValor_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_TraitsSetting)]
        public float FactorValor { get; set; } = 0.31F;
        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_Factor_Traits_FactorHonor_Name, 0f, 3f, HintText = Text_RevoltModel_Factor_Traits_FactorHonor_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_TraitsSetting)]
        public float FactorHonor { get; set; } = 0.31F;
        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_Factor_Traits_FactorGenerosity_Name, 0f, 3f, HintText = Text_RevoltModel_Factor_Traits_FactorGenerosity_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_TraitsSetting)]
        public float FactorGenerosity { get; set; } = 0.31F;

        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_Factor_Traits_FactorCaculation_Name, 0f, 3f, HintText = Text_RevoltModel_Factor_Traits_FactorCaculation_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_TraitsSetting)]
        public float FactorCaulation { get; set; } = 0.31F;
        #endregion

        #region RelationFactor

        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_Factor_Relationships_FactorRelation_Name, 0f, 3f, HintText = Text_RevoltModel_Factor_Relationships_FactorRelation_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_RelationshipsSetting)]
        public float FactorRelation { get; set; } = 0.31F;

        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_Factor_Relationships_FactorInform_Name, 0f, 3f, HintText = Text_RevoltModel_Factor_Relationships_FactorInform_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_RelationshipsSetting)]
        public float FactorInforom { get; set; } = 0.31F;

        #endregion

        #region SpouseFactor

        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_Factor_Spouses_FactorSingleOverAge_Name, 0f, 3f, HintText = Text_RevoltModel_Factor_Spouses_FactorSingleOverAge_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_Spouses_Setting)]
        public float FactorSingleOverAge { get; set; } = 0.31F;

        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_Factor_Spouses_FactorMarried_Name, 0f, 3f, HintText = Text_RevoltModel_Factor_Spouses_FactorMarried_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_Spouses_Setting)]
        public float FactorMarried { get; set; } = 0.31F;

        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_Factor_Spouses_FactorSingleUnderAge_Name, 0f, 3f, HintText = Text_RevoltModel_Factor_Spouses_FactorSingleUnderAge_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_Spouses_Setting)]
        public float FactorSingleUnderAge { get; set; } = 0.31F;

        #endregion

        #region OthersFactor

        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_Factor_Others_FactorRenown_Name, 0f, 3f, HintText = Text_RevoltModel_Factor_Others_FactorRenown_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_Others_Setting)]
        public float FactorRenown { get; set; } = 0.31F;

        [XmlElement]
        [SettingPropertyFloatingInteger(Text_RevoltModel_Factor_Others_FactorAmbition_Name, 0f, 3f, HintText = Text_RevoltModel_Factor_Others_FactorAmbition_Hint, RequireRestart = false)]
        [SettingPropertyGroup(Text_RevoltModel_Factor_Others_Setting)]
        public float FactorAmbition { get; set; } = 0.31F;

        #endregion

        #endregion

        #endregion
        #endregion


    }
}

Color Picker?

First off, great job with this!

And now to my question, are there any plans to implement color pickers, so we are able to pick colors in the settings? Or is there such a feature already and I'm just missing it?

Thanks in advance!

Settings not displayed - 1.1.14

@Aragas#7671 finally! ok - so there's no more crashing - it basically is doing this now:
1> Checks to see if ModLib or MBOptionScreen module is running
2> If so, checks to see if modlib.dll has been loaded into the current AppDomain
3> If not, it checks to see which one to use - if only MBOptionScreen is found it loads modlib.dll from your module folder.
4> Then it loads my modlibsettings dll up via reflection and gets the settings from it.
5> It then sets the primary settings class to whatever settings system it found gave it.

Issue: It still doesn't show TournamentXPanded in the ModOptions list unless another modlib mod has already loaded.
I can confirm that Bannerlord does not load every dll in the bin folder by default. Your modlib is not loaded until I do it manually, unless a different mod that directly references modlib is loaded first.
This may also be way TournamentXP doesn't show in the list, unless a different modlib mod is loaded first - you can't scan my assembly for modlib classes, they don't exist. My suggestion would be when I call the normal SettingsDatabase.Register you add my settings to the list. If already are, then I'm unsure now what the issue is. My calls to your ModLib are returning a valid settings class.

(I did learn a ton about reflection today so it's been a good exercise so far)

Edit: Unless the modlib options aren't supposed to load if ModLib proper doesn't exist? When I load the primary ModLib mod, and yours, everything is working I think.
I thought/think you were saying that even without the main ModLib module, modlib mods would still have an option screen.

Nexusmods deployment

The standalone module should be uploaded automatically to nexusmods when merging into master.

Check first what we can do with providing the description when doing the release

Using "Set Defaults" button breaks config

Configs no longer update after pressing the Set Defaults button. The UI updates properly when changing settings, but when fetching the configs it always pulls the pre-defaulted settings. It is broken until a game restart.

Multiple Menu Options

I know that you're aware of the bug, but I'm creating this for tracking purposes.

When multiple versions of MCM are operating, duplicate "Mod Options" menu options appear on the main menu and the campaign Escape menu.

Fluent API Question

I'm having trouble figuring out how to use the Fluent API Default Settings Builder with MCMv3.14 Integrated and Bannerlord version e1.4.0.

I have this code in a singleton, which builds and registers some global settings:

private FluentGlobalSettings _settings;
float _testFloat = 0;

public void BuildSettings()
{
    var builder = new DefaultSettingsBuilder("Test_v1", "Test Mod")
        .SetFormat("json")
        .SetFolderName(SubModule.ModuleFolderName)
        .SetSubFolder("")
        .CreateGroup("Test Group", groupBuilder =>
            groupBuilder.AddFloatingInteger("Test Name", 0f, 20f,
                new ProxyRef<float>(() => _testFloat, (value) => _testFloat = value),
                floatBuilder => floatBuilder
                    .SetHintText("Test Hint")));

    _settings = builder.BuildAsGlobal();
    _settings.Register();
}

And I can't seem to get those test settings to appear in the MCM Mod Options menu no matter when I call my BuildSettings method in the lifecycle. I do see the option menus for the three MCM modules though, I just don't see mine.

When exactly should we be registering settings that are built with the Fluent API? The Wiki mentioned it should be after the player loads into a campaign, but it still doesn't seem to appear in the in-game MCM Mod Options menu when I attempt to register settings by calling my BuildSettings method from an MBSubModuleBase.OnGameLoaded override:

public override void OnGameLoaded(Game game, object initializerObject)
{
    base.OnGameLoaded(game, initializerObject);
    Settings.Instance.BuildSettings();
}

Am I doing something obviously wrong here, or am I just misunderstanding something?

Improve MSBuild Targets

Make a single task that will:

  • Copy the _Data folder to Module/
  • Clear Module/bin folder
  • Copy new binaries into Modules/bin
  • Replace $version$ in SubModule.xml

Fluent API Tests

  • Ensure that properties are created in the right groups
  • Ensure that nested groups are correct
  • Ensure that group toggles work
  • Ensure that each BaseSetting/PropertyGroup/Property is changed

Does MBOption Screen Support Localization?

Hi Aragas:

Nice work here,

I read the Wiki. It says that Localization is supported in MBOptionScreen.

I am thinking of migrating to MBOptionScreen.

How to localize the setting text with you lib?
Maybe you could provide us with some examples, please?

Thanks

v2 api constructors are not accepting parameters other than displayName

Using the latest version v2.0.10 from NuGet.
Things like
[SettingPropertyBool(displayName: "Test Bool", order: -1, requireRestart: false, hintText: "This is a v2 bool value definition")]
[SettingPropertyGroup("v2 Test")]
public bool TestBool { get; set; } = true;

Are not working because SettingPropertyBool only accepts displayName, and order, requiredRestart, hintText is causing compile time error:
The best overload for 'SettingPropertyBoolAttribute' does not have a parameter named 'order'

Per Character Settings in v4

Hi, I was playing around with my mod settings and testing if I could convert them from global settings to per character settings.
However it seems like AttributePerCharacterSettings is not implemented in v4.
Is this not recommended? Is there a replacement or will this be supported in the future? Thanks!

user error as usual

Settings details:

  • Top-layer groups: 4
  • Nested groups: 15
  • Highest level of nesting: 2
  • Number of settings, including main toggle groups: anything higher than 52 causes the issue.
  • Using JSON storage format

If I remove any 4 settings from the mod, everything goes back to normal.
I've deleted the mod's config and that does not solve the issue.
Using non-integrated MCM 3.1.5 from NuGet.
Mod's source is available at ashakoor/UnlimitLord.

EDIT: Nevermind, I'm just an idiot. Forgot to edit a main toggle while copy-pasting. Turns out having a float as a main toggle breaks the whole mod options menu.

Incompatible Saving

Hard to explain this one, but hopefully you'll understand.

With ModLib from Mipen everything works fine when not running alongside MBOptionScreen.

With MBOptionScreen it is saving as well, but ModLib mods aren't reading this save. So while you can make the save to enable something, it won't register with ModLib on the next startup of the game.

In order to get ModLib mods to save and read, you must do so prior to using a mod with MBOptionScreen.

Just some feedback I received. ~

Integration Tests

The accidental release of 3.1.10 has shown that there were some kind of incompatibility issues between 3.1.9 and 3.1.10.

  • Create test project for testing cases when multiple implementations are loaded into the AppDomain
  • Find a way to trigger manually game's prefab loading without starting the whole game
  • Find a way to trigger manually game's module loading mechanism

When is settings guaranteed to be loaded?

It is stated in the wiki that "you should not use Settings.Instance in OnSubModuleLoad() as the setting might still not be loaded depending on mod loading order".
However, I need to harmony patch some Deserailize methods, for example TaleWorlds.Core.WeaponComponentData.Deserailize, before any xml is loaded. By my own observations, xmls are loaded when a save is loaded. So I suppose the patching has to be done before OnGameStart() to be safe.
So if it is not reliable to get settings in OnSubModuleLoad(), when is settings guaranteed to be loaded?

Huge performance drop in MCM v3

I tried to port my mod from MBOptionScreen v2.0.10 to MCM.Integrated v3.1.0, and the performance drops badly. Both are using attributes api v2.
I ran a performance profiler of CPU in Visual Studio comparing both versions:
MBOptionScreen is taking no more than 0.05% of CPU time;
MCM is using more than 30%. DefaultDropdown::ctor is using more than 20% alone (and there is only a single instance of DefaultDropdown is my settings class). GlobalSettings::get_instance is using 7%, and AttributeGlobalSettings::ctor is using 2.46%.
It looks like AttributeGlobalSettings.Instance is not working correctly, that everytime it is called it creates and returns a new instance, otherwise the ctors should only be called once and not eating so much CPU time.

Can I just disable its setting saving functionality and handle it myself?

I uses .ini for my mod's settings, I personally like to take control over how settings are saved and loaded.

I only need this lib (or the ModLib I am current using) to provide the UI.

It's like this in my code:

        [SettingPropertyGroup("Fire Arrow Misc")]
        [SettingProperty("Fire Arrow Allowed Units", 0, 6, "What type of units are allowed to use fire arrows, 0=None, 1=Player, 2=Heroes, 3=Companions, 4=Allies, 5=Enemies, 6=All")]
        [XmlElement]
        public int AllowedUnitType
        {
            get => (int)FireLordConfig.AllowedUnitType;
            set => FireLordConfig.AllowedUnitType = (FireLordConfig.UnitType)value;
        }

FireLordConfig does all the saving and loading for me. All I need from this lib or ModLib is only the UI part.
So is it possible to add a API to disable file saving for this lib?

And also

[SettingPropertyBool(displayName: "Setting Name", order: 0, requireRestart: false, hintText: "Setting explanation.")]

throw this at me:
Class does not contain a constructor taking 4 parameters ...
Looks like some v2 annotations doesn't have a constructor taking 4 parameters.
Guess it's not ready for use yet, I am gonna try v1 for the time being.

Exceptions fetching settings using MBOptionScreen v2.0.8

I'm getting some bug reports from users of my mod of crashing when fetching settings:
https://imgur.com/MrYh6Ma

It does not occur on a fresh e1.3 install with just my mod running so I suspect there is some conflict with another version of MBOptionScreen or Modlib.

SubModule XML:
https://github.com/Katarn2000x/DiplomacyFixes/blob/master/SubModule.xml

Settings:
https://github.com/Katarn2000x/DiplomacyFixes/blob/master/Settings.cs

Crash Source:
https://github.com/Katarn2000x/DiplomacyFixes/blob/master/Patches/PoliticalStagnationAndBorderIncidentCampaignBehaviorPatch.cs#L17

MCM v4.0.7 crash on startup with Bannerlord 1.5.4

I think this is a known crash already, but I don't see it reported here or with much detail in the nexus discussions for the mod, so hopefully this is helpful.

I'm using:
Harmony 2.0.2.27 ("for fixed launcher" build)
Butterlib v1.0.12
UIExtenderEx v1.0.3

Load order is:
BetterExceptionWindow
Harmony
Butterlib
UIExtenderEx
MCM
MCMv4 MCMv3 Integration
MCMv4 ModLib v1/v13 Integration

here is the info from BetterExceptionWindow:

  • Reasons
    Source: MCMv4.UI.v4.0.7
    The type initializer for 'MCM.UI.Functionality.Injectors.PrefabInjector' threw an exception.

  • Inner exception
    Source: 0Harmony
    Value cannot be null. Parameter name: fieldInfo

  • Callstacks
    Protip: Use a debugger like dnSpy or Visual studio to trace the source of error, by stepping the program line by line.

Inner exception callstack:
at HarmonyLib.AccessTools.FieldRefAccess[T,F](FieldInfo fieldInfo)
at MCM.UI.Functionality.Injectors.PrefabInjector..cctor()

Outer exception callstack:
at MCM.UI.Functionality.Injectors.PrefabInjector.InjectDocumentAndCreate(String name, XmlDocument doc)
at MCM.UI.Functionality.Loaders.PrefabsLoader.Inject(BaseResourceHandler resourceInjector)
at MCM.UI.MCMUISubModule.<>c.b__2_0(Object s, SubscriptionEventArgs e)
at System.EventHandler`1.Invoke(Object sender, TEventArgs e)
at Bannerlord.ButterLib.DelayedSubModule.DelayedSubModuleManager.BaseOnBeforeInitialModuleScreenSetAsRootPostfix(MBSubModuleBase __instance)
at TaleWorlds.MountAndBlade.Module.SetInitialModuleScreenAsRootScreen()
at TaleWorlds.MountAndBlade.Module.OnApplicationTick_Patch1(Module this, Single dt)

Version Injection

Version should be taken from Directory.Build.props and injected into necessary files

  • Inject version into SubModule.xml
  • Inject version into nuspec

ISettingsFormat Serialization Tests

  • Ensure that BaseJsonSettingsFormat serializes correctly
  • Ensure that the settings are saved in each ISettingsFormat implementation
  • Ensure that the settings are loaded in each ISettingsFormat implementation

Foolproof Tests

  • Ensure that custom invalid setting classes will not crash MCM or prevent correct settings from loading

Long texts in string settings

When using very long texts in the settings they overflow the text box. The text editing dialog also presents some glitches, and when trying to select the whole text the game throws:

System.ArgumentOutOfRangeException: 'Length cannot be less than zero.
Parameter name: length'

The example images are settings containing banner codes generated with the online banner editor

Images

image

image

NexusMods Page

General:

  • Logo (done by drogean)

Description:

  • Installation steps
  • Troubleshooting. DLL Unblocking

Exception when initializing MBOptionScreenSubModuleV2010

Crash Report Image: https://imgur.com/mKPJfzl

This is a very rare crashing.

Only one of my mod's user encounters this when using the launcher to start the game.

I remote access his computer. No matter I include MBOptionScreen.v2.0.10.dll in my module or as a reference from a standalone MCM.

This error happens.

His game and other mods are fine. But the initialization of MCM just keeps crashing for couldn't detect the 'id' parameter.

And what's your discord channel, please? I would like to join.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.