Skip to content

Commit

Permalink
feat: allow integration of poc's configuration file in DADG's module …
Browse files Browse the repository at this point in the history
…(#26)

* Use a Harmony patch to override POC's default configuration path
* Move dadg.config.xml at the root config folder
* Add dadg's poc config file named poc.config.json at root config folder
* Rename code source configuration folder to technical-config
* Document POC's integration
* Change logging configuration so that the level is a single uppercase letter. This ensures logs to be well aligned regardless of the log's severity
  • Loading branch information
JoeFwd committed Feb 17, 2024
1 parent bcdf73d commit 67a04ca
Show file tree
Hide file tree
Showing 11 changed files with 960 additions and 19 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,4 @@ AssetPackages/
Shaders/

#DADG
/config/
/config/nlog.config
File renamed without changes.
818 changes: 818 additions & 0 deletions config/poc.config.json

Large diffs are not rendered by default.

37 changes: 37 additions & 0 deletions doc/poc.integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# POC Integration

## What is POC?

POC is a Bannerlord mod allowing to freely set specific or randomised colours to banners and shields for given kingdoms, clans and units. For instance, companions or unit types can have their own colours and banners.

For more information, check out [POC's nexus page](https://www.nexusmods.com/mountandblade2bannerlord/mods/792?tab=description).

## DADG Use Cases

### Configuration

The highly customisable mod uses a unique configuration file named `config.json` which is expected to be at its root module folder. POC does not natively read the configuration file anywhere else.

This causes third party mods needing to fully integrate the mod in its module folder to rely on an external POC instance. It also does not support the Steam Workshop.

So in order to kill two birds with one stone, we implemented a [Harmony patch](../src/DellarteDellaGuerra/Patches/PocConfigReaderPatch.cs) addressing both issues.

It detects whether POC is integrated in DADG or is in an external module and overrides the configuration path to a custom location. For now, the POC configuration is expected to be in DellarteDellaGuerra config folder and named `poc.config.json`.

You can check out [DADG's configuration in the repository](../config/poc.config.json).

### Heraldry

All English clans and kingdoms have a custom banner. We use POC to set custom banners as Native enforces all clans to have the same background colour as their kingdom.

Custom banners can be created with the [online Banner Editor](https://bannerlord.party/banner).

![Heraldry](https://github.com/DellarteDellaGuerraTeam/DellarteDellaGuerraMap/assets/32904771/463f7959-c06d-4a7d-9587-256fe30048d5)

### Randomised Colour Clothing

POC enables Bannerlord armour pieces to have random colours. It allows to have many variations of an armour piece. It also allows to have many civilian clothes.

![Battle](https://github.com/DellarteDellaGuerraTeam/DellarteDellaGuerraMap/assets/32904771/aa2bdce5-c72f-42ce-a245-af50ae2e4e77)

![Town](https://github.com/DellarteDellaGuerraTeam/DellarteDellaGuerraMap/assets/32904771/9850b611-3d88-4934-be68-cd7d9b88622e)
11 changes: 6 additions & 5 deletions src/DellarteDellaGuerra.sln
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ModuleData", "ModuleData",
..\ModuleData\items.xml = ..\ModuleData\items.xml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{9D03C908-71BC-4E5D-BA67-F673DF4F1CFC}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{F1AF53B1-6B28-4A2D-A967-B7BE6EC15C84}"
ProjectSection(SolutionItems) = preProject
config\nlog.dev.config = config\nlog.dev.config
config\nlog.prod.config = config\nlog.prod.config
config\dadg.config.xml = config\dadg.config.xml
technical-config\nlog.dev.config = technical-config\nlog.dev.config
technical-config\nlog.prod.config = technical-config\nlog.prod.config
..\config\dadg.config.xml = ..\config\dadg.config.xml
..\config\poc.config.json = ..\config\poc.config.json
EndProjectSection
EndProject
Global
Expand All @@ -57,7 +58,7 @@ Global
GlobalSection(NestedProjects) = preSolution
{CB20C6C8-2857-4B1E-9C00-265893C094E3} = {12CCA2B5-A874-47B3-BB43-799275014D7B}
{F3FF0EA7-9E28-4D27-9FA8-70754A123DF7} = {12CCA2B5-A874-47B3-BB43-799275014D7B}
{9D03C908-71BC-4E5D-BA67-F673DF4F1CFC} = {12CCA2B5-A874-47B3-BB43-799275014D7B}
{F1AF53B1-6B28-4A2D-A967-B7BE6EC15C84} = {12CCA2B5-A874-47B3-BB43-799275014D7B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B3D4AB65-9162-4EE2-9413-1867C12DC041}
Expand Down
6 changes: 2 additions & 4 deletions src/DellarteDellaGuerra/DellarteDellaGuerra.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,13 @@
<PackageReference Include="Bannerlord.ReferenceAssemblies.Native" Version="$(GameVersion).*-*" PrivateAssets="All" />
</ItemGroup>

<Target Name="Copy config files to bin folder" BeforeTargets="BeforeBuild">
<Target Name="Copy technical config files to bin folder" BeforeTargets="BeforeBuild">
<Message Importance="high" Text="Copy config files to bin folder" />
<ItemGroup>
<ConfigFolderOutput Include="$(MSBuildThisFileDirectory)..\..\config\" />
<LogConfigFile Include="$(MSBuildThisFileDirectory)..\config\nlog.$(Env).config" />
<DadgConfigFile Include="$(MSBuildThisFileDirectory)..\config\dadg.config.xml" />
<LogConfigFile Include="$(MSBuildThisFileDirectory)..\technical-config\nlog.$(Env).config" />
</ItemGroup>
<Copy SourceFiles="@(LogConfigFile)" DestinationFiles="$(MSBuildThisFileDirectory)..\..\config\nlog.config" />
<Copy SourceFiles="@(DadgConfigFile)" DestinationFolder="$(MSBuildThisFileDirectory)..\..\config" />
</Target>

</Project>
2 changes: 1 addition & 1 deletion src/DellarteDellaGuerra/Logging/LoggerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ private static LoggingConfiguration GetDefaultConfiguration(string logPath)
var logfile = new FileTarget("logfile")
{
FileName = path,
Layout = "[${date:format=yyyy-MM-dd HH\\:mm\\:ss} | ${uppercase:${level}} | ${logger}] ${message}${exception:format=tostring}"
Layout = "[${date:format=yyyy-MM-dd HH\\:mm\\:ss} | ${uppercase:${level:format=FirstCharacter}} | ${logger}] ${message}${exception:format=tostring}"
};
#if DEBUG
config.AddRule(LogLevel.Debug, LogLevel.Fatal, logfile);
Expand Down
87 changes: 87 additions & 0 deletions src/DellarteDellaGuerra/Patches/PocConfigReaderPatch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using DellarteDellaGuerra.Logging;
using DellarteDellaGuerra.Utils;
using HarmonyLib;
using NLog;

namespace DellarteDellaGuerra.Patches;

/**
* <summary>
* This script patches the PocColor mod to override the config file path.
* It is expected to be in the DellarteDellaGuerra config folder and named poc.config.json.
* </summary>
* <remarks>
* It has to be called explicitly and can not rely on Harmony's automatic patching.
* This is due to the fact that the PocColor mod is not a reference of the DellarteDellaGuerra mod.
* </remarks>
*/
public class PocConfigReaderPatch
{
private static readonly Logger Logger = LoggerFactory.GetLogger<PocConfigReaderPatch>();

private PocConfigReaderPatch() { }

/**
* <summary>
* Patches the PocColorMod assembly to read the config file from the DellarteDellaGuerra config folder.
* If the PocColorMod assembly is not loaded, then this method does nothing.
* </summary>
*/
public static void Patch(Harmony harmony)
{
MethodInfo? originalMethod = ResolveOriginalMethod();
MethodInfo? patchMethod = ResolvePatchMethod();
if (originalMethod == null || patchMethod == null)
{
Logger.Warn($"{nameof(PocConfigReaderPatch)} failed to resolve the original method or the patch method");
return;
}
harmony.Patch(originalMethod, transpiler: new HarmonyMethod(patchMethod));
}

private static MethodInfo? ResolveOriginalMethod()
{
return AppDomain.CurrentDomain.GetAssemblies().SingleOrDefault(assembly => assembly.GetName().Name == "PocColor")
?.GetType("PocColor.PocColorMod")
?.GetMethod("OnGameInitializationFinished", BindingFlags.Instance | BindingFlags.Public);
}

private static MethodInfo? ResolvePatchMethod()
{
return typeof(PocConfigReaderPatch).GetMethod(nameof(Transpiler), BindingFlags.Static | BindingFlags.NonPublic);
}

private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> codeInstructions)
{
var instructions = codeInstructions.ToList();
var isInstructionFound = false;

foreach (var instruction in instructions)
{
if (instruction.opcode != OpCodes.Ldstr || !instruction.OperandIs("..\\..\\modules\\PocColor\\config.json"))
{
continue;
}
string? configFolderPath = ResourceLocator.GetConfigurationFolderPath();
if (configFolderPath == null)
{
continue;
}
instruction.operand = Path.Combine(configFolderPath, "poc.config.json");
isInstructionFound = true;
break;
}

if (!isInstructionFound)
{
Logger.Error($"{nameof(PocConfigReaderPatch)} failed to find the config file path instruction");
}
return instructions;
}
}
10 changes: 5 additions & 5 deletions src/DellarteDellaGuerra/SubModule.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
using System;
using System.IO;
using System.Reflection;
using System.Xml;
using DellarteDellaGuerra.Configuration.Providers;
using DellarteDellaGuerra.DadgCampaign;
using DellarteDellaGuerra.GameManager;
using DellarteDellaGuerra.Logging;
using DellarteDellaGuerra.Patches;
using DellarteDellaGuerra.Utils;
using HarmonyLib;
using TaleWorlds.CampaignSystem;
using TaleWorlds.Core;
using TaleWorlds.ModuleManager;
using TaleWorlds.MountAndBlade;
using NLog;

Expand All @@ -20,7 +19,7 @@ public class SubModule : MBSubModuleBase
{
private static readonly Logger Logger = LoggerFactory.GetLogger<SubModule>();
private static readonly Harmony Harmony = new ("mod.harmony.dellartedellaguerra");
private readonly CampaignBehaviourDisabler _campaignBehaviourDisabler = new();
private readonly CampaignBehaviourDisabler _campaignBehaviourDisabler = new ();

protected override void OnBeforeInitialModuleScreenSetAsRoot()
{
Expand All @@ -32,7 +31,8 @@ protected override void OnSubModuleLoad()
{
try
{
Harmony.PatchAll();
PocConfigReaderPatch.Patch(Harmony);
Harmony.PatchAll();
} catch (Exception e)
{
Logger.Error("Harmony patches failed: {}", e);
Expand Down Expand Up @@ -88,4 +88,4 @@ private void LoadDadgBattleScenes()
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

<targets>
<target xsi:type="File" name="allfile" fileName="${basedir}/../../Modules/DellarteDellaGuerra/log/dadg-${shortdate}.log"
layout="[${date:format=yyyy-MM-dd HH\:mm\:ss} | ${uppercase:${level}} | ${logger}] ${message}${exception:format=tostring}" />
layout="[${date:format=yyyy-MM-dd HH\:mm\:ss} | ${uppercase:${level:format=FirstCharacter}} | ${logger}] ${message}${exception:format=tostring}" />
<target
xsi:type="Console"
name="console"
layout="[${date:format=yyyy-MM-dd HH\:mm\:ss} | ${uppercase:${level}} | ${logger}] ${message}${exception:format=tostring}" />
layout="[${date:format=yyyy-MM-dd HH\:mm\:ss} | ${uppercase:${level:format=FirstCharacter}} | ${logger}] ${message}${exception:format=tostring}" />
</targets>

<rules>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<targets>
<target xsi:type="File" name="allfile" fileName="${basedir}/../../Modules/DellarteDellaGuerra/log/dadg-${shortdate}.log"
layout="[${date:format=yyyy-MM-dd HH\:mm\:ss} | ${uppercase:${level}} | ${logger}] ${message}${exception:format=tostring}" />
layout="[${date:format=yyyy-MM-dd HH\:mm\:ss} | ${uppercase:${level:format=FirstCharacter}} | ${logger}] ${message}${exception:format=tostring}" />
</targets>

<rules>
Expand Down

0 comments on commit 67a04ca

Please sign in to comment.