├── .editorconfig ├── .gitattributes ├── .github └── workflows │ ├── ci.yml │ └── mod-builder.yml ├── .gitignore ├── CHANGEME.Directory.Build.props ├── CHANGES.md ├── CommonBase.props ├── CommonBattleTech.props ├── CommonNetStandard.props ├── Directory.Packages.props ├── HarmonyXInterop ├── Harmony109Interop │ ├── Attributes.cs │ ├── CodeInstruction.cs │ ├── Harmony109Interop.csproj │ ├── HarmonyInstance.cs │ ├── HarmonyMethod.cs │ ├── HarmonySharedState.cs │ ├── ILCopying │ │ └── Emitter.cs │ ├── Patch.cs │ ├── PatchFunctions.cs │ ├── PatchProcessor.cs │ ├── Priority.cs │ ├── Tools │ │ ├── AccessCache.cs │ │ ├── AccessTools.cs │ │ ├── DynamicTools.cs │ │ ├── Extensions.cs │ │ ├── FileLog.cs │ │ ├── PatchTools.cs │ │ └── Traverse.cs │ └── Transpilers.cs ├── Harmony12Interop │ ├── Attributes.cs │ ├── CodeInstruction.cs │ ├── Extras │ │ ├── DelegateTypeFactory.cs │ │ ├── FastAccess.cs │ │ └── MethodInvoker.cs │ ├── Harmony12Interop.csproj │ ├── HarmonyInstance.cs │ ├── HarmonyMethod.cs │ ├── HarmonySharedState.cs │ ├── ILCopying │ │ ├── Emitter.cs │ │ └── ILInstruction.cs │ ├── Patch.cs │ ├── PatchFunctions.cs │ ├── PatchProcessor.cs │ ├── Priority.cs │ ├── Tools │ │ ├── AccessCache.cs │ │ ├── AccessTools.cs │ │ ├── Extensions.cs │ │ ├── FileLog.cs │ │ ├── PatchTools.cs │ │ ├── SymbolExtensions.cs │ │ └── Traverse.cs │ └── Transpilers.cs ├── HarmonyXInterop │ ├── HarmonyInterop.cs │ ├── HarmonyXInterop.csproj │ ├── Logging.cs │ ├── PatchModel.cs │ ├── PrefixInterop.cs │ ├── TranspilerInterop.cs │ └── WrapperClassBuilder.cs └── README.md ├── INSTALL.md ├── LICENSE ├── ModTek.Common ├── Globals │ └── Paths.cs ├── Logging │ ├── ConsoleLoggerAdapter.cs │ └── SimpleLogger.cs ├── ModTek.Common.csproj └── Utils │ ├── AssemblyUtils.cs │ ├── CSharpUtils.cs │ ├── DebugUtils.cs │ ├── DictionaryExtensions.cs │ └── FileUtils.cs ├── ModTek.Injectors ├── AssemblyCache.cs ├── InjectionCacheManifest.cs ├── Logger.cs ├── ModTek.Injectors.csproj └── Runner.cs ├── ModTek.InjectorsTask ├── ITaskItemExtensions.cs ├── ModTek.InjectorsTask.csproj ├── ModTek.InjectorsTask.props ├── ModTek.InjectorsTask.targets ├── ModTekInjectorsRunner.cs └── ModTekInjectorsTask.props ├── ModTek.Preloader ├── Entrypoint.cs ├── Harmony12X │ ├── AssemblyOriginalPathTracker.cs │ ├── DynamicShimInjector.cs │ ├── HarmonyVersion.cs │ ├── ShimCacheManifest.cs │ └── ShimInjectorPatches.cs ├── IEnumerableExtensions.cs ├── InjectorsAppDomain.cs ├── Loader │ ├── AssemblyTracker.cs │ ├── Cleaner.cs │ ├── Config.cs │ ├── LegacyChecker.cs │ ├── Preloader.cs │ └── SingleInstanceEnforcer.cs ├── Logger.cs ├── ModTek.Preloader.csproj ├── doorstop_config.ini └── run.sh ├── ModTek.sln ├── ModTek ├── Features │ ├── AdvJSONMerge │ │ ├── AdvJSONMergeFeature.cs │ │ ├── AdvancedJSONMerge.cs │ │ ├── Instruction.cs │ │ └── MergeAction.cs │ ├── AssembliesLoader │ │ └── CustomAssembliesLoader.cs │ ├── BetterReflectionCache │ │ └── BetterReflectionCache_Patches.cs │ ├── CustomDebugSettings │ │ ├── DebugSettingsFeature.cs │ │ └── Patches │ │ │ ├── DebugBridge_DEFAULT_SETTINGS_FILE_PATH_Patch.cs │ │ │ ├── DebugBridge_GetCustomSettingsFilePath_Patch.cs │ │ │ └── DebugBridge_GetStreamingAssetsFilePath_Patch.cs │ ├── CustomEncounterLayers │ │ ├── EncounterLayer.cs │ │ └── MetadataDatabaseExtensions.cs │ ├── CustomGameTips │ │ ├── GameTipsFeature.cs │ │ └── Patches │ │ │ └── GameTipList_ctor_Patch.cs │ ├── CustomResources │ │ ├── CustomResourcesFeature.cs │ │ └── InternalCustomResourceType.cs │ ├── CustomSVGAssets │ │ ├── Patches │ │ │ └── SVGAsset_Patches.cs │ │ └── SVGAssetFeature.cs │ ├── CustomSoundBankDefs │ │ ├── ProcessParameters.cs │ │ ├── Public │ │ │ ├── ModTek.cs │ │ │ ├── SoundBankDef.cs │ │ │ ├── SoundBankType.cs │ │ │ └── SoundBanksProcessHelper.cs │ │ ├── SoundBanksFeature.cs │ │ └── SoundBanksPatches.cs │ ├── CustomSoundBanks │ │ ├── Patches │ │ │ └── LoadedAudioBank_LoadBank_Patch.cs │ │ └── SoundBanksFeature.cs │ ├── CustomTags │ │ ├── CustomTag.cs │ │ ├── CustomTagFeature.cs │ │ ├── CustomTagSet.cs │ │ └── MetadataDatabaseExtensions.cs │ ├── CustomVideos │ │ ├── Patches │ │ │ └── BinkMediaPlayer_Play_Patch.cs │ │ └── VideosFeature.cs │ ├── DebugDump │ │ └── DebugDumpFeature.cs │ ├── LoadAtBattleStart │ │ └── Patches │ │ │ └── Contract_RequestConversations_Patch.cs │ ├── LoadingCurtainEx │ │ ├── DataManagerStats │ │ │ ├── DataManagerStats.cs │ │ │ ├── DumpLoadRequests.cs │ │ │ └── LoadingCurtainStatsText.cs │ │ ├── LoadingCurtainErrorText.cs │ │ ├── LoadingCurtain_Init_Patch.cs │ │ ├── LoadingCurtain_LateUpdate_Patch.cs │ │ └── LoadingCurtain_ShowUntil_Patch.cs │ ├── Logging │ │ ├── AppenderFile.cs │ │ ├── AppenderSettings.cs │ │ ├── AppenderUnityConsole.cs │ │ ├── FastBuffer.cs │ │ ├── FastSimd.cs │ │ ├── FilterBuilder.cs │ │ ├── FilterSettings.cs │ │ ├── Formatter.cs │ │ ├── FormattingHelpers.cs │ │ ├── HarmonyXLoggerAdapter.cs │ │ ├── LightWeightBlockingQueue.cs │ │ ├── LinePrefixToFilterTransformer.cs │ │ ├── LogLevelExtension.cs │ │ ├── LogStream.cs │ │ ├── LogStreamImpl │ │ │ ├── FileStreamImpl.cs │ │ │ ├── ILogStream.cs │ │ │ ├── MonoIoFileStreamImpl.cs │ │ │ └── Win32ApiImpl.cs │ │ ├── LoggingFeature.cs │ │ ├── LoggingSettings.cs │ │ ├── MTLoggerAsyncQueue.cs │ │ ├── MTLoggerMessageDto.cs │ │ └── Patches │ │ │ ├── Exception_ctor_Patch.cs │ │ │ ├── HarmonyManipulator_LogPatchException_Patch.cs │ │ │ ├── LogImpl_Flush.cs │ │ │ ├── LogImpl_IsEnabledFor_Patch.cs │ │ │ ├── LogImpl_LogAtLevel_Patch.cs │ │ │ ├── LogImpl_set_Level_Patch.cs │ │ │ ├── Logger_CaptureUnityLogs_Patch.cs │ │ │ ├── SqlMapper_ExecuteImpl_Patch.cs │ │ │ ├── SqliteCommand_CommandText_Setter_Patch.cs │ │ │ └── Thread_StartInternal_Patch.cs │ ├── Manifest │ │ ├── BTConstants.cs │ │ ├── BTRL │ │ │ ├── BetterBTRL.cs │ │ │ ├── BetterCPI.cs │ │ │ ├── TypedManifest.cs │ │ │ └── VersionManifestEntryComparer.cs │ │ ├── CacheKey.cs │ │ ├── CustomType.cs │ │ ├── FileVersionTuple.cs │ │ ├── MDD │ │ │ ├── AddendumUtils.cs │ │ │ ├── DataAddendumWrapper.cs │ │ │ ├── MDDBCache.cs │ │ │ ├── MDDBIndexer.cs │ │ │ └── VersionManifestEntryExtensions.cs │ │ ├── MTContentPackManager.cs │ │ ├── Merges │ │ │ ├── MergeCache.cs │ │ │ └── MergeCacheEntry.cs │ │ ├── Mods │ │ │ ├── ModDefExExtensions.cs │ │ │ ├── ModDefExLoading.cs │ │ │ ├── ModDefsDatabase.cs │ │ │ └── ModState.cs │ │ ├── ModsManifest.cs │ │ ├── ModsManifestPreloader.cs │ │ ├── Patches │ │ │ ├── AssetBundleManager_AssetBundleNameToFileURL_Patch.cs │ │ │ ├── AssetBundleManager_AssetBundleNameToFilepath_Patch.cs │ │ │ ├── BattleTechResourceLocator_Patches.cs │ │ │ ├── ContentPackIndex_IsResourceOwned_Patch.cs │ │ │ ├── ContentPackIndex_PatchMDD_Patch.cs │ │ │ ├── ContentPackIndex_TryFinalizeDataLoad_Patch.cs │ │ │ ├── DataManager_ProcessPrewarmRequests_Patch.cs │ │ │ ├── LoadRequest_PopPendingRequest_Patch.cs │ │ │ ├── MetadataDatabase_MDD_DB_PATH_Patch.cs │ │ │ ├── MetadataDatabase_MDD_TMP_PATH_Patch.cs │ │ │ └── SimGame_MDDExtensions_UpdateContract_Patch.cs │ │ └── Public │ │ │ ├── DataAddendumEntry.cs │ │ │ ├── ModDefEx.cs │ │ │ ├── ModEntry.cs │ │ │ ├── ModTek.cs │ │ │ └── PreloaderAPI.cs │ ├── ModLoaderSupport │ │ └── Patches │ │ │ └── ModLoaderPatches.cs │ └── Profiler │ │ ├── Patches │ │ ├── JSONSerializationUtility_RehydrateObjectFromDictionary_Patch.cs │ │ ├── JSON_ToObject_Patch.cs │ │ └── UIManager_LateUpdate_Patch.cs │ │ └── ProfilerStats.cs ├── GlobalUsings.cs ├── Log.cs ├── Misc │ ├── Configuration.cs │ ├── FilePaths.cs │ └── ModTekCacheStorage.cs ├── ModTek.cs ├── ModTek.csproj ├── Patches │ ├── ActivateAfterInit.cs │ └── VersionInfo.cs ├── Public │ ├── BTRL.cs │ ├── CustomResources.cs │ ├── FilePaths.cs │ └── NullableLogger.cs ├── UI │ └── ProgressPanel.cs ├── Util │ ├── AssemblyUtil.cs │ ├── FastRandom.cs │ ├── HBSJsonUtils.cs │ ├── LoadOrder.cs │ ├── RunOnlyOnceHandler.cs │ └── Stopwatch │ │ ├── MTStopwatch.cs │ │ ├── MTStopwatchStats.cs │ │ ├── MTStopwatchWithCallback.cs │ │ └── MTStopwatchWithSampling.cs └── modtekassetbundle ├── ModTekInjector ├── Injector.cs └── ModTekInjector.csproj ├── ModTekSimpleInjector ├── Injector.cs ├── ModTekSimpleInjector.Example.xml ├── ModTekSimpleInjector.csproj ├── SimpleInjection.cs └── XmlDeserializationTypes.cs ├── README.md ├── doc ├── ADVANCED_JSON_MERGING.md ├── CONTENT_PACK_ASSETS.md ├── CONTRIBUTE.md ├── CUSTOM_TYPE_CUSTOMTAGS.md ├── CUSTOM_TYPE_DEBUGSETTINGS.md ├── CUSTOM_TYPE_SOUNDBANKS.md ├── CUSTOM_TYPE_SVGASSET.md ├── DATA_ADDENDUM_ENTRIES.md ├── DEVELOPMENT_GUIDE.md ├── HARMONY12X.md ├── LOGGING.md ├── MANIFEST.md ├── MOD_DLL.md ├── MOD_JSON.md ├── MOD_JSON_FORMAT.md ├── PLATFORM_FILE_TREES.md ├── PRELOADER.md ├── PRIMER.md └── QUICKSTART.md └── examples ├── Directory.Packages.props └── ModTemplate ├── Main.cs ├── ModTemplate.csproj ├── Patches └── VersionInfo_GetReleaseVersion_Patch.cs └── mod.json /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto encoding=UTF-8 5 | *.sh text eol=lf 6 | 7 | ############################################################################### 8 | # Set default behavior for command prompt diff. 9 | # 10 | # This is need for earlier builds of msysgit that does not have it on by 11 | # default for csharp files. 12 | # Note: This is only used by command line 13 | ############################################################################### 14 | *.cs diff=csharp text 15 | *.vb text 16 | 17 | ############################################################################### 18 | # Set the merge driver for project and solution files 19 | # 20 | # Merging from the command prompt will add diff markers to the files if there 21 | # are conflicts (Merging from VS is not affected by the settings below, in VS 22 | # the diff markers are never inserted). Diff markers may cause the following 23 | # file extensions to fail to load in VS. An alternative would be to treat 24 | # these files as binary and thus will always conflict and require user 25 | # intervention with every merge. To do so, just uncomment the entries below 26 | ############################################################################### 27 | #*.sln merge=binary 28 | #*.csproj merge=binary 29 | #*.vbproj merge=binary 30 | #*.vcxproj merge=binary 31 | #*.vcproj merge=binary 32 | #*.dbproj merge=binary 33 | #*.fsproj merge=binary 34 | #*.lsproj merge=binary 35 | #*.wixproj merge=binary 36 | #*.modelproj merge=binary 37 | #*.sqlproj merge=binary 38 | #*.wwaproj merge=binary 39 | 40 | ############################################################################### 41 | # behavior for image files 42 | # 43 | # image files are treated as binary by default. 44 | ############################################################################### 45 | #*.jpg binary 46 | #*.png binary 47 | #*.gif binary 48 | 49 | ############################################################################### 50 | # diff behavior for common document formats 51 | # 52 | # Convert binary document formats to text before diffing them. This feature 53 | # is only available from the command line. Turn it on by uncommenting the 54 | # entries below. 55 | ############################################################################### 56 | #*.doc diff=astextplain 57 | #*.DOC diff=astextplain 58 | #*.docx diff=astextplain 59 | #*.DOCX diff=astextplain 60 | #*.dot diff=astextplain 61 | #*.DOT diff=astextplain 62 | #*.pdf diff=astextplain 63 | #*.PDF diff=astextplain 64 | #*.rtf diff=astextplain 65 | #*.RTF diff=astextplain 66 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | build: 9 | uses: ./.github/workflows/mod-builder.yml 10 | with: 11 | checkout-directory: 'ModTek' 12 | modtek-download-url: '' # don't download ModTek when ModTek is being built! 13 | build-script: | 14 | build_modtek() { 15 | btdir="$1" 16 | zipname="$2" 17 | dotnet build --verbosity normal --configuration Release -p:BattleTechGameDir="$btdir" 18 | cd "$btdir" 19 | rm -fr "BattleTech_Data/" 20 | find . -type f -printf "%m:%p\n" 21 | # set permissions and also check if files exist (chmod 644) 22 | chmod 755 run.sh 23 | chmod 644 winhttp.dll 24 | chmod 644 Mods/ModTek/lib/*.dll 25 | 7z a -tzip -mx9 "$DIST_DIR/$zipname" -ir!. 26 | cd - 27 | dotnet clean --verbosity normal --configuration Release -p:BattleTechGameDir="$btdir" 28 | } 29 | 30 | build_modtek "$BATTLETECH_DIR" "ModTek.zip" 31 | release-notes: | 32 | > **Note** 33 | > **ModTekInjector.exe was replaced by [UnityDoorstop](https://github.com/NeighTools/UnityDoorstop)**. 34 | > Injectors must not be run manually, that is now done by the `ModTekPreloader` automatically during the games startup. 35 | 36 | ModTek.zip contains the ModTek tools. Unzip the contents into your game's location, so that `winhttp.dll` appears in the same folder as `BattleTech.exe`. 37 | See [Changes](https://github.com/BattletechModders/ModTek/blob/master/CHANGES.md) and [Readme](https://github.com/BattletechModders/ModTek/blob/master/README.md). 38 | secrets: inherit 39 | -------------------------------------------------------------------------------- /CHANGEME.Directory.Build.props: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | C:\Games\Steam\SteamApps\common\BATTLETECH\ 8 | 9 | 10 | -------------------------------------------------------------------------------- /CommonBase.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | Library 9 | 13 10 | embedded 11 | 12 | 13 | 14 | $(BattleTechGameDir)\Mods\ModTek\lib\ 15 | 16 | 17 | 18 | 19 | all 20 | runtime; build; native; contentfiles; analyzers 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /CommonBattleTech.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | net472 7 | 8 | {HintPathFromItem}; 9 | $(BattleTechGameDir)\BattleTech_Data\Managed 10 | 11 | true 12 | 13 | 14 | 15 | 16 | All 17 | 18 | 19 | 20 | 21 | 22 | 23 | False 24 | 25 | 26 | False 27 | 28 | 29 | False 30 | 31 | 32 | -------------------------------------------------------------------------------- /CommonNetStandard.props: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | netstandard2.0 11 | 12 | -------------------------------------------------------------------------------- /Directory.Packages.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | true 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /HarmonyXInterop/Harmony109Interop/Attributes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Harmony 4 | { 5 | public enum PropertyMethod 6 | { 7 | Getter, 8 | Setter 9 | } 10 | 11 | public class HarmonyAttribute : Attribute 12 | { 13 | public HarmonyMethod info = new HarmonyMethod(); 14 | } 15 | 16 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] 17 | public class HarmonyPatch : HarmonyAttribute 18 | { 19 | public HarmonyPatch() 20 | { 21 | } 22 | 23 | public HarmonyPatch(Type type) 24 | { 25 | info.originalType = type; 26 | } 27 | 28 | public HarmonyPatch(string methodName) 29 | { 30 | info.methodName = methodName; 31 | } 32 | 33 | public HarmonyPatch(string propertyName, PropertyMethod type) 34 | { 35 | var prefix = type == PropertyMethod.Getter ? "get_" : "set_"; 36 | info.methodName = prefix + propertyName; 37 | } 38 | 39 | public HarmonyPatch(Type[] parameter) 40 | { 41 | info.parameter = parameter; 42 | } 43 | 44 | public HarmonyPatch(Type type, string methodName, Type[] parameter = null) 45 | { 46 | info.originalType = type; 47 | info.methodName = methodName; 48 | info.parameter = parameter; 49 | } 50 | 51 | public HarmonyPatch(Type type, Type[] parameter = null) 52 | { 53 | info.originalType = type; 54 | info.parameter = parameter; 55 | } 56 | } 57 | 58 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 59 | public class HarmonyPriority : HarmonyAttribute 60 | { 61 | public HarmonyPriority(int prioritiy) 62 | { 63 | info.prioritiy = prioritiy; 64 | } 65 | } 66 | 67 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 68 | public class HarmonyBefore : HarmonyAttribute 69 | { 70 | public HarmonyBefore(params string[] before) 71 | { 72 | info.before = before; 73 | } 74 | } 75 | 76 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 77 | public class HarmonyAfter : HarmonyAttribute 78 | { 79 | public HarmonyAfter(params string[] after) 80 | { 81 | info.after = after; 82 | } 83 | } 84 | 85 | // If you don't want to use the special method names you can annotate 86 | // using the following attributes: 87 | 88 | [AttributeUsage(AttributeTargets.Method)] 89 | public class HarmonyPrepare : Attribute 90 | { 91 | } 92 | 93 | [AttributeUsage(AttributeTargets.Method)] 94 | public class HarmonyTargetMethod : Attribute 95 | { 96 | } 97 | 98 | [AttributeUsage(AttributeTargets.Method)] 99 | public class HarmonyPrefix : Attribute 100 | { 101 | } 102 | 103 | [AttributeUsage(AttributeTargets.Method)] 104 | public class HarmonyPostfix : Attribute 105 | { 106 | } 107 | 108 | [AttributeUsage(AttributeTargets.Method)] 109 | public class HarmonyTranspiler : Attribute 110 | { 111 | } 112 | } -------------------------------------------------------------------------------- /HarmonyXInterop/Harmony109Interop/CodeInstruction.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Reflection.Emit; 4 | 5 | namespace Harmony 6 | { 7 | public class CodeInstruction 8 | { 9 | public OpCode opcode; 10 | public object operand; 11 | public List