Skip to content

Commit 960dc4e

Browse files
committed
Switched to a ButterLib architecture
Added Interceptor redirection
1 parent 1488b8b commit 960dc4e

22 files changed

+699
-88
lines changed

.github/workflows/publish.yml

+32-4
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,36 @@ jobs:
2626
github-token: ${{secrets.GITHUB_TOKEN}}
2727

2828
- name: Build Bannerlord.IronPython
29-
run: dotnet pack src/Bannerlord.IronPython/Bannerlord.IronPython.csproj --configuration Release -p:GameFolder="$PWD/bannerlord";
30-
shell: pwsh
29+
run: |
30+
$impl = $PWD.Path + '/bannerlord-implementations';
31+
$path = $PWD.Path + '/bannerlord';
32+
$final = $path + '/Modules/Bannerlord.IronPython/bin/Win64_Shipping_Client/';
33+
$proj = 'src/Bannerlord.IronPython.Implementation/Bannerlord.IronPython.Implementation.csproj';
34+
$pdll = $path + '/Modules/Bannerlord.IronPython/bin/Win64_Shipping_Client/Bannerlord.IronPython.Implementation.*.dll';
35+
$ppdb = $path + '/Modules/Bannerlord.IronPython/bin/Win64_Shipping_Client/Bannerlord.IronPython.Implementation.*.pdb';
36+
# The folders are required to be created before executing the script
37+
New-Item -ItemType directory -Force -Path $impl;
38+
New-Item -ItemType directory -Force -Path $path;
39+
[string[]]$gameversions = Get-Content -Path supported-game-versions.txt;
40+
# Last entry is the Minimal version. We will use Bannerlord.IronPython.dll from there
41+
For ($i = 0; $i -le $gameversions.Length - 1; $i++)
42+
{
43+
$gameversion = $gameversions[$i];
44+
$version = $gameversion.substring(1);
45+
$constgameversion = $gameversion.replace(".", "");
46+
dotnet clean $proj --configuration Release;
47+
dotnet build $proj --configuration Release -p:OverrideGameVersion=$gameversion -p:GameFolder="$path" -p:GameVersionConstant="$constgameversion";
48+
# Copy Implementations to the Implementations folder
49+
Copy-Item $pdll $impl/;
50+
Copy-Item $ppdb $impl/;
51+
}
52+
# Copy Implementations to the Module
53+
Copy-Item $impl/* $final;
54+
# Delete Implementations folder
55+
Remove-Item -Recurse $impl;
56+
shell: pwsh
57+
env:
58+
BANNERLORD_BUTR_UPLOAD_URL: ${{secrets.BANNERLORD_BUTR_UPLOAD_URL}}
3159

3260
- name: Upload Bannerlord folder
3361
uses: actions/upload-artifact@v3
@@ -67,9 +95,9 @@ jobs:
6795
- name: Run ChangelogParser
6896
id: changelog
6997
run: |
70-
vers="$(bannerlord_changelog_parser latestversion -f "$PWD/src/Bannerlord.IronPython/changelog.txt")"
98+
vers="$(bannerlord_changelog_parser latestversion -f "$PWD/changelog.txt")"
7199
echo "::set-output name=mod_version::$vers"
72-
desc="$(bannerlord_changelog_parser fulldescription -f "$PWD/src/Bannerlord.IronPython/changelog.txt")"
100+
desc="$(bannerlord_changelog_parser fulldescription -f "$PWD/changelog.txt")"
73101
desc="${desc//'%'/'%25'}"
74102
desc="${desc//$'\n'/'%0A'}"
75103
desc="${desc//$'\r'/'%0D'}"

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,4 @@ MigrationBackup/
348348

349349
# Ionide (cross platform F# VS Code tools) working folder
350350
.ionide/
351+
/bannerlord/*

build/common.props

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<!--EXTERNAL_PROPERTIES: TargetFramework;BANNERLORD_GAME_DIR;BANNERLORD_STABLE_DIR;BANNERLORD_BETA_DIR;GITHUB_ACTIONS;MSBuildThisFileDirectory;OverrideGameVersion-->
2+
<Project>
3+
4+
<!--Development Variables-->
5+
<PropertyGroup>
6+
<IronPythonVersion>3.4.0</IronPythonVersion>
7+
<Version>$(IronPythonVersion).1</Version>
8+
9+
<!--Harmony Version-->
10+
<HarmonyVersion>2.2.1</HarmonyVersion>
11+
<HarmonyExtensionsVersion>3.1.0.61</HarmonyExtensionsVersion>
12+
<HarmonyAnalyzerVersion>1.0.1.44</HarmonyAnalyzerVersion>
13+
<ButterLibVersion>2.1.13</ButterLibVersion>
14+
<!--BuildResources Version-->
15+
<BuildResourcesVersion>1.0.1.68</BuildResourcesVersion>
16+
<BUTRSharedVersion>2.0.0.86</BUTRSharedVersion>
17+
<BUTRModuleManagerVersion>4.0.118</BUTRModuleManagerVersion>
18+
</PropertyGroup>
19+
20+
<PropertyGroup>
21+
<Authors>BUTR Team</Authors>
22+
<Company></Company>
23+
<Product>IronPython Support for Bannerlord</Product>
24+
</PropertyGroup>
25+
26+
<PropertyGroup>
27+
<IsMinimal>true</IsMinimal>
28+
<IsMinimal Condition="$(Configuration.Contains('Minimal'))">true</IsMinimal>
29+
<IsStable>false</IsStable>
30+
<IsStable Condition="$(Configuration.Contains('Stable'))">true</IsStable>
31+
<IsBeta>false</IsBeta>
32+
<IsBeta Condition="$(Configuration.Contains('Beta'))">true</IsBeta>
33+
</PropertyGroup>
34+
35+
<PropertyGroup>
36+
<SGVFile>$([System.IO.File]::ReadAllText($(MSBuildThisFileDirectory)/../supported-game-versions.txt))</SGVFile>
37+
</PropertyGroup>
38+
<ItemGroup>
39+
<SGVItem Include="$([System.Text.RegularExpressions.Regex]::Split($(SGVFile), `\r\n|\r|\n`))" />
40+
</ItemGroup>
41+
42+
<PropertyGroup Condition="$(OverrideGameVersion) == ''">
43+
<GameVersionFallback>e1.1.0</GameVersionFallback>
44+
<!-- Parsing supported-game-versions.txt -->
45+
<SGVLineCount>$([System.Text.RegularExpressions.Regex]::Split($(SGVFile), `\r\n|\r|\n`).Length)</SGVLineCount>
46+
<SGVLastEntryIndex>$([MSBuild]::Subtract($(SGVLineCount), 1))</SGVLastEntryIndex>
47+
<!-- First enrty is Beta, second Stable, last Minimal -->
48+
<FirstLine Condition="'$(SGVLineCount)' &gt; 0">$([System.Text.RegularExpressions.Regex]::Split($(SGVFile), `\r\n|\r|\n`)[0])</FirstLine>
49+
<SecondLine Condition="'$(SGVLineCount)' &gt; 1">$([System.Text.RegularExpressions.Regex]::Split($(SGVFile), `\r\n|\r|\n`)[1])</SecondLine>
50+
<LastLine Condition="'$(SGVLineCount)' &gt; 0">$([System.Text.RegularExpressions.Regex]::Split($(SGVFile), `\r\n|\r|\n`)[$(SGVLastEntryIndex)])</LastLine>
51+
52+
<SecondLine Condition="'$(SecondLine)' == ''">$(FirstLine)</SecondLine>
53+
<LastLine Condition="'$(LastLine)' == ''">$(SecondLine)</LastLine>
54+
<!-- -->
55+
<GameBetaVersion>$(FirstLine)</GameBetaVersion>
56+
<GameStableVersion>$(SecondLine)</GameStableVersion>
57+
<GameMinimalVersion>$(LastLine)</GameMinimalVersion>
58+
<!-- -->
59+
<GameVersionWithPrefix Condition="$(IsMinimal)">$(GameMinimalVersion)</GameVersionWithPrefix>
60+
<GameVersionWithPrefix Condition="$(IsStable)">$(GameStableVersion)</GameVersionWithPrefix>
61+
<GameVersionWithPrefix Condition="$(IsBeta)">$(GameBetaVersion)</GameVersionWithPrefix>
62+
<GameVersionWithPrefix Condition="$(GameVersionWithPrefix) == ''">$(GameVersionFallback)</GameVersionWithPrefix>
63+
<!-- -->
64+
<GameVersion>$(GameVersionWithPrefix.Substring(1))</GameVersion>
65+
</PropertyGroup>
66+
<PropertyGroup Condition="$(OverrideGameVersion) != ''">
67+
<GameVersionWithPrefix>$(OverrideGameVersion)</GameVersionWithPrefix>
68+
<GameVersion>$(GameVersionWithPrefix.Substring(1))</GameVersion>
69+
</PropertyGroup>
70+
<PropertyGroup>
71+
<GameVersionFlat>$([System.String]::Copy('$(GameVersion)').Replace('.',''))</GameVersionFlat>
72+
<GameVersionConstant>e$(GameVersionFlat)</GameVersionConstant>
73+
</PropertyGroup>
74+
75+
<PropertyGroup>
76+
<!--Bannerlord's Root Folder. Leave empty if you want it to be tried to be autoresolved.-->
77+
<GameFolder Condition="$(IsStable)">$(BANNERLORD_STABLE_DIR)</GameFolder>
78+
<GameFolder Condition="$(IsBeta)">$(BANNERLORD_BETA_DIR)</GameFolder>
79+
<GameFolder Condition="$(GameFolder) == ''">$(BANNERLORD_GAME_DIR)</GameFolder>
80+
</PropertyGroup>
81+
82+
<!--Automatic Path Resolution-->
83+
<PropertyGroup>
84+
<!--Windows-->
85+
<!--Get from Registry (not working with dotnet right now)-->
86+
<GameFolder Condition="!Exists($(GameFolder)) AND $(OS) == 'Windows_NT'">$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 261550@InstallLocation)</GameFolder>
87+
<!--Set a default value if registry value is missing-->
88+
<GameFolder Condition="!Exists($(GameFolder)) AND $(OS) == 'Windows_NT'">C:\Program Files (x86)\Steam\steamapps\common\Mount &amp; Blade II Bannerlord</GameFolder>
89+
<!--Unix-->
90+
<GameFolder Condition="!Exists($(GameFolder)) AND $(OS) == 'Unix'">~/.steam/root/steamapps/common/Mount &amp; Blade II Bannerlord</GameFolder>
91+
</PropertyGroup>
92+
93+
94+
<!--GitHub Actions-->
95+
<PropertyGroup Condition="$(GITHUB_ACTIONS) == 'true'">
96+
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
97+
</PropertyGroup>
98+
<!--NuGet SorceLink-->
99+
<PropertyGroup>
100+
<PublishRepositoryUrl>true</PublishRepositoryUrl>
101+
<IncludeSymbols>true</IncludeSymbols>
102+
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
103+
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
104+
</PropertyGroup>
105+
<!--SorceLink-->
106+
<PropertyGroup>
107+
<Deterministic>true</Deterministic>
108+
<EmbedUntrackedSources>true</EmbedUntrackedSources>
109+
</PropertyGroup>
110+
<!--SorceLink-->
111+
<ItemGroup>
112+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/>
113+
</ItemGroup>
114+
<!--CI Builds-->
115+
<ItemGroup Condition="$(TargetFramework) == 'net472' AND $(OS) != 'Windows_NT'">
116+
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2">
117+
<PrivateAssets>all</PrivateAssets>
118+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
119+
</PackageReference>
120+
</ItemGroup>
121+
122+
<ItemGroup Condition="'$(GITHUB_ACTIONS)' != 'true'">
123+
<PackageReference Include="BUTR.Harmony.Analyzer" Version="$(HarmonyAnalyzerVersion)">
124+
<PrivateAssets>all</PrivateAssets>
125+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
126+
</PackageReference>
127+
</ItemGroup>
128+
129+
</Project>

build/common.targets

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!--EXTERNAL_PROPERTIES: GameVersionWithPrefix;BANNERLORD_GAME_DIR;BANNERLORD_STABLE_DIR;BANNERLORD_BETA_DIR-->
2+
<Project>
3+
4+
<Target Name="WarningsForEnvs" BeforeTargets="BeforeCompile">
5+
<Warning Condition="$(BANNERLORD_GAME_DIR) == '' AND $(BANNERLORD_STABLE_DIR) == '' AND $(BANNERLORD_BETA_DIR) == ''" Text="Environment variable 'BANNERLORD_GAME_DIR' is not set!"></Warning>
6+
<Warning Condition="$(BANNERLORD_GAME_DIR) == '' AND $(BANNERLORD_STABLE_DIR) == ''" Text="Environment variable 'BANNERLORD_STABLE_DIR' is not set!"></Warning>
7+
<Warning Condition="$(BANNERLORD_GAME_DIR) == '' AND $(BANNERLORD_BETA_DIR) == ''" Text="Environment variable 'BANNERLORD_BETA_DIR' is not set!"></Warning>
8+
</Target>
9+
10+
<Target Name="AddGameVersionMetadaAssemblyAttributes" BeforeTargets="CoreGenerateAssemblyInfo">
11+
<ItemGroup>
12+
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute" Condition="$(GameVersionWithPrefix) != ''" >
13+
<_Parameter1>GameVersion</_Parameter1>
14+
<_Parameter2>$(GameVersionWithPrefix)</_Parameter2>
15+
</AssemblyAttribute>
16+
</ItemGroup>
17+
</Target>
18+
19+
</Project>
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using Bannerlord.BUTR.Shared.Helpers;
2+
using Bannerlord.BUTRLoader;
3+
using Bannerlord.IronPython.Implementation.Utils;
4+
5+
using HarmonyLib;
6+
using HarmonyLib.BUTR.Extensions;
7+
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Xml;
11+
12+
using TaleWorlds.Engine;
13+
14+
using Module = TaleWorlds.MountAndBlade.Module;
15+
16+
namespace Bannerlord.IronPython.Implementation
17+
{
18+
[BUTRLoaderInterceptor]
19+
public static class BUTRLoadingInterceptor
20+
{
21+
private static readonly AccessTools.FieldRef<Module, Dictionary<string, Type>>? LoadedSubModuleTypes =
22+
AccessTools2.FieldRefAccess<Module, Dictionary<string, Type>>("_loadedSubmoduleTypes");
23+
24+
public static void OnInitializeSubModulesPrefix()
25+
{
26+
var loadedSubModuleTypes = LoadedSubModuleTypes?.Invoke(Module.CurrentModule);
27+
28+
var baseFolder = Utilities.GetBasePath();
29+
30+
foreach (var moduleInfo in ModuleInfoHelper.GetLoadedModules())
31+
{
32+
var moduleFolder = System.IO.Path.Combine(baseFolder, "Modules", moduleInfo.Id);
33+
var xmlDocument = new XmlDocument();
34+
xmlDocument.Load(System.IO.Path.Combine(moduleFolder, "SubModule.xml"));
35+
36+
var moduleNode = xmlDocument.SelectSingleNode("Module");
37+
38+
var subModules = moduleNode?.SelectSingleNode("SubModules");
39+
var subModuleList = subModules?.SelectNodes("SubModulePython");
40+
for (var i = 0; i < subModuleList?.Count; i++)
41+
{
42+
var subModuleNode = subModuleList[i];
43+
var name = subModuleNode?.SelectSingleNode("Name")?.Attributes["value"]?.InnerText ?? string.Empty;
44+
var scriptName = subModuleNode?.SelectSingleNode("ScriptName")?.Attributes["value"]?.InnerText ?? string.Empty;
45+
var subModuleClassType = subModuleNode?.SelectSingleNode("SubModuleClassType")?.Attributes["value"]?.InnerText ?? string.Empty;
46+
loadedSubModuleTypes?.Add(name, new WrappedSubModulePythonType(moduleFolder, scriptName, subModuleClassType));
47+
}
48+
}
49+
}
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net472</TargetFramework>
5+
<Platforms>x64</Platforms>
6+
<LangVersion>9.0</LangVersion>
7+
<Nullable>enable</Nullable>
8+
9+
<Configurations>Stable_Debug;Stable_Release;Beta_Debug;Beta_Release</Configurations>
10+
<DefineConstants>$(DefineConstants);$(GameVersionConstant)</DefineConstants>
11+
12+
<AssemblyName>$(MSBuildProjectName).$(GameVersion)</AssemblyName>
13+
</PropertyGroup>
14+
15+
<!--Module Creation-->
16+
<PropertyGroup>
17+
<ModuleId>Bannerlord.IronPython</ModuleId>
18+
<ModuleName>IronPython Support</ModuleName>
19+
</PropertyGroup>
20+
<!--Module Creation-->
21+
22+
<ItemGroup>
23+
<PackageReference Include="Bannerlord.ReferenceAssemblies.Core.EarlyAccess" Version="$(GameVersion).*" PrivateAssets="All" />
24+
25+
<PackageReference Include="Bannerlord.BuildResources" Version="$(BuildResourcesVersion)" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
26+
27+
<PackageReference Include="Bannerlord.BUTR.Shared" Version="$(BUTRSharedVersion)" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
28+
<PackageReference Include="Bannerlord.ModuleManager.Source" Version="$(BUTRModuleManagerVersion)" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
29+
<PackageReference Include="Lib.Harmony" Version="$(HarmonyVersion)" IncludeAssets="compile" />
30+
<PackageReference Include="Harmony.Extensions" Version="$(HarmonyExtensionsVersion)" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
31+
<PackageReference Include="Bannerlord.ButterLib" Version="$(ButterLibVersion)" PrivateAssets="all" IncludeAssets="compile" />
32+
<PackageReference Include="IronPython" Version="$(IronPythonVersion)-beta1" />
33+
<PackageReference Include="IsExternalInit" Version="1.0.2" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive"/>
34+
<PackageReference Include="Nullable" Version="1.3.0" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive"/>
35+
</ItemGroup>
36+
37+
<ItemGroup>
38+
<Reference Include="Microsoft.CSharp" />
39+
</ItemGroup>
40+
41+
<ItemGroup>
42+
<ProjectReference Include="..\Bannerlord.IronPython\Bannerlord.IronPython.csproj" />
43+
</ItemGroup>
44+
45+
</Project>
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using TaleWorlds.MountAndBlade;
22

3-
namespace Bannerlord.IronPython
3+
namespace Bannerlord.IronPython.Implementation
44
{
55
public class SubModule : MBSubModuleBase { }
66
}

src/Bannerlord.IronPython/SubModulePython.cs renamed to src/Bannerlord.IronPython.Implementation/SubModulePython.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Bannerlord.IronPython.Utils;
1+
using Bannerlord.IronPython.Implementation.Utils;
22

33
using IronPython.Hosting;
44

@@ -9,7 +9,7 @@
99
using TaleWorlds.Core;
1010
using TaleWorlds.MountAndBlade;
1111

12-
namespace Bannerlord.IronPython
12+
namespace Bannerlord.IronPython.Implementation
1313
{
1414
internal class SubModuleIronPython : MBSubModuleBase
1515
{

src/Bannerlord.IronPython/Utils/EmptySubModule.cs renamed to src/Bannerlord.IronPython.Implementation/Utils/EmptySubModule.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
using TaleWorlds.MountAndBlade;
44

5-
namespace Bannerlord.IronPython.Utils
5+
namespace Bannerlord.IronPython.Implementation.Utils
66
{
77
internal class EmptySubModule : MBSubModuleBaseWrapper
88
{

src/Bannerlord.IronPython/Utils/WrappedConstructorInfo.cs renamed to src/Bannerlord.IronPython.Implementation/Utils/WrappedConstructorInfo.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using System.Globalization;
33
using System.Reflection;
44

5-
namespace Bannerlord.IronPython.Utils
5+
namespace Bannerlord.IronPython.Implementation.Utils
66
{
77
internal sealed class WrappedConstructorInfo : ConstructorInfo
88
{

src/Bannerlord.IronPython/Utils/WrappedSubModulePythonType.cs renamed to src/Bannerlord.IronPython.Implementation/Utils/WrappedSubModulePythonType.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using System.Globalization;
55
using System.Reflection;
66

7-
namespace Bannerlord.IronPython.Utils
7+
namespace Bannerlord.IronPython.Implementation.Utils
88
{
99
internal class WrappedSubModulePythonType : Type
1010
{

src/Bannerlord.IronPython/_Module/SubModule.xml renamed to src/Bannerlord.IronPython.Implementation/_Module/SubModule.xml

+4-13
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,10 @@
4040
<!-- Community Dependency Metadata -->
4141
<SubModules>
4242
<SubModule>
43-
<Name value="$moduleid$" />
43+
<Name value="$moduleid$ Implementation Loader" />
4444
<DLLName value="$moduleid$.dll" />
45-
<SubModuleClassType value="$moduleid$.SubModule" />
46-
<Assemblies>
47-
<Assembly value="IronPython.dll"/>
48-
<Assembly value="IronPython.Modules.dll"/>
49-
<Assembly value="IronPython.SQLite.dll"/>
50-
<Assembly value="IronPython.Wpf.dll"/>
51-
<Assembly value="Microsoft.Dynamic.dll"/>
52-
<Assembly value="Microsoft.Scripting.dll"/>
53-
<Assembly value="Microsoft.Scripting.Metadata.dll"/>
54-
</Assemblies>
55-
<Tags/>
45+
<SubModuleClassType value="$moduleid$.ImplementationLoaderSubModule" />
46+
<Tags />
5647
</SubModule>
5748
</SubModules>
58-
</Module>
49+
</Module>

0 commit comments

Comments
 (0)