Skip to content

Commit

Permalink
- Added mods enabler
Browse files Browse the repository at this point in the history
  • Loading branch information
Enclave2020 committed Jan 29, 2019
1 parent 6e8f0a2 commit 66a738d
Show file tree
Hide file tree
Showing 9 changed files with 354 additions and 1 deletion.
27 changes: 27 additions & 0 deletions Fallout76Proxy.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="packages\Costura.Fody.3.3.2\build\Costura.Fody.props" Condition="Exists('packages\Costura.Fody.3.3.2\build\Costura.Fody.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
Expand All @@ -12,6 +13,8 @@
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
Expand All @@ -36,6 +39,18 @@
<ApplicationIcon>Fallout76.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="Costura, Version=3.3.2.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL">
<HintPath>packages\Costura.Fody.3.3.2\lib\net40\Costura.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib">
<HintPath>References\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="INIFileParser, Version=2.5.2.0, Culture=neutral, PublicKeyToken=79af7b307b65cf3c, processorArchitecture=MSIL">
<HintPath>packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll</HintPath>
</Reference>
<Reference Include="Sharp.BSA.BA2">
<HintPath>References\Sharp.BSA.BA2.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Management" />
Expand All @@ -50,11 +65,23 @@
<Compile Include="BethesdaGames.cs" />
<Compile Include="BethesdaLauncher.cs" />
<Compile Include="GameManager.cs" />
<Compile Include="ModManager.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Fallout76.ico" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="packages\Fody.3.3.5\build\Fody.targets" Condition="Exists('packages\Fody.3.3.5\build\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\Fody.3.3.5\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Fody.3.3.5\build\Fody.targets'))" />
<Error Condition="!Exists('packages\Costura.Fody.3.3.2\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.3.3.2\build\Costura.Fody.props'))" />
</Target>
</Project>
4 changes: 4 additions & 0 deletions FodyWeavers.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Costura />
</Weavers>
111 changes: 111 additions & 0 deletions FodyWeavers.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="Costura" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="PreloadOrder" type="xs:string">
<xs:annotation>
<xs:documentation>The order of preloaded assemblies, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:all>
<xs:attribute name="CreateTemporaryAssemblies" type="xs:boolean">
<xs:annotation>
<xs:documentation>This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeDebugSymbols" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls if .pdbs for reference assemblies are also embedded.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCompression" type="xs:boolean">
<xs:annotation>
<xs:documentation>Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCleanup" type="xs:boolean">
<xs:annotation>
<xs:documentation>As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="LoadAtModuleInit" type="xs:boolean">
<xs:annotation>
<xs:documentation>Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IgnoreSatelliteAssemblies" type="xs:boolean">
<xs:annotation>
<xs:documentation>Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged32Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="PreloadOrder" type="xs:string">
<xs:annotation>
<xs:documentation>The order of preloaded assemblies, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
142 changes: 142 additions & 0 deletions ModManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
using IniParser;
using IniParser.Model;
using Microsoft.Win32;
using SharpBSABA2;
using SharpBSABA2.BA2Util;
using System;
using System.Collections.Generic;
using System.IO;

namespace Fallout76Proxy
{
class ModManager
{
/* STRANGE MOD LOADING
https://www.nexusmods.com/fallout76/mods/162
https://www.nexusmods.com/fallout76/mods/60
https://www.nexusmods.com/fallout76/mods/183
https://www.nexusmods.com/fallout76/mods/91
*/

class ModConflictException : Exception { public ModConflictException(string message) : base(message) { } };
class Fallout76NotInstalled : Exception { public Fallout76NotInstalled(string message) : base(message) { } };

enum LoadType
{
Default,
StartUp
}

LoadType GetLoadType(BA2 ba2)
{
foreach (ArchiveEntry file in ba2.Files)
{
if (file.FileName.Contains("fonts_"))
{
return LoadType.StartUp;
}
}

return LoadType.Default;
}

string GetFallout76Path()
{
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Fallout 76");
if (registryKey == null)
{
throw new Fallout76NotInstalled("Can't detect Fallout 76 installation!");
}

string path = (string) registryKey.GetValue("Path");

if (String.IsNullOrEmpty(path))
{
throw new Fallout76NotInstalled("Can't detect Fallout 76 directory!");
}

path = path.Replace("\"", "");

if (!Directory.Exists($"{path}\\Data"))
{
throw new Fallout76NotInstalled("Fallout 76 data directory missed!");
}

return path;
}

public void Process()
{
Dictionary<string, string> conflicts = new Dictionary<string, string>();

string sResourceArchive2List = "SeventySix - ATX_Main.ba2, SeventySix - ATX_Textures.ba2";
string sResourceStartUpArchiveList = "SeventySix - Interface.ba2, SeventySix - Localization.ba2, SeventySix - Shaders.ba2, SeventySix - Startup.ba2";

string[] ba2Archives = Directory.GetFiles($"{GetFallout76Path()}\\Data\\", "*.ba2");

Console.WriteLine($"Detected {ba2Archives.Length} mods.");

foreach (string ba2Archive in ba2Archives)
{
// skip F76 files
if (ba2Archive.Contains("SeventySix -"))
{
continue;
}

BA2 ba2 = new BA2(ba2Archive);

foreach (ArchiveEntry file in ba2.Files)
{
if (conflicts.ContainsKey(file.FullPath))
{
throw new ModConflictException(String.Format("Mod {0} conflicts with {1}. Remove one of them.", ba2.FileName, conflicts[file.FullPath]));
}

conflicts.Add(file.FullPath, ba2.FileName);
}

LoadType modLoadType = GetLoadType(ba2);
switch (modLoadType)
{
case LoadType.Default:
sResourceArchive2List += String.Format(", {0}", ba2.FileName);
break;

case LoadType.StartUp:
sResourceStartUpArchiveList += String.Format(", {0}", ba2.FileName);
break;
}
}

WriteFallout76Customs(sResourceArchive2List, sResourceStartUpArchiveList);
}

void WriteFallout76Customs(string sResourceArchive2List, string sResourceStartUpArchiveList)
{
FileIniDataParser parser = new FileIniDataParser();

string myDocumentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string fallout76CustomPath = $"{myDocumentsPath}\\My Games\\Fallout 76\\Fallout76Custom.ini";

IniData data = new IniData();

if (File.Exists(fallout76CustomPath))
{
// Remove readonly
File.SetAttributes(fallout76CustomPath, FileAttributes.Normal);

data = parser.ReadFile(fallout76CustomPath);
}

data["Archive"]["sResourceArchive2List"] = sResourceArchive2List;
data["Archive"]["sResourceStartUpArchiveList"] = sResourceStartUpArchiveList;

// Empty old data
data["Archive"].RemoveKey("sResourceArchiveList2");
data["Archive"].RemoveKey("sResourceIndexFileList");

File.WriteAllText(fallout76CustomPath, data.ToString());
}
}
}
Loading

0 comments on commit 66a738d

Please sign in to comment.