Compare commits

...
Author SHA1 Message Date
Tannin 5fa02a3045 small stuff in preparation of release 2015-05-31 00:36:16 +02:00
Tannin 53a94be2fd - NCC now built to use "modern" controls 2015-05-24 18:41:21 +02:00
Tannin e61f4aff90 Merge with branch1.2 2015-01-24 19:34:12 +01:00
Tannin 7fbc9f0770 - bugfix: some fomod installers still didn't "see" other installed files
- bugfix: the way the gamemode-proxy was installed caused inconsistent data in some calls (since 1.2.15)
2015-01-11 11:12:15 +01:00
7 changed files with 115 additions and 25 deletions
+6 -1
View File
@@ -44,8 +44,13 @@ namespace Nexus.Client.CLI
public bool DataFileExists(string p_strPath)
{
string unfixedPath = p_strPath;
if (unfixedPath.StartsWith("data", StringComparison.OrdinalIgnoreCase))
{
unfixedPath = unfixedPath.Substring(5);
}
foreach (string path in SearchPaths) {
if (File.Exists(Path.Combine(path, p_strPath)))
if (File.Exists(Path.Combine(path, unfixedPath)))
{
return true;
}
+27
View File
@@ -3,10 +3,36 @@ using Nexus.Client.Games;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace Nexus.Client.CLI
{
public class GameModeInterceptorSelector : IInterceptorSelector
{
public IInterceptor[] SelectInterceptors(Type type, MethodInfo method, IInterceptor[] interceptors)
{
if (IsGetter(method))
{
return interceptors;
}
else
{
return null;
}
}
private bool IsGetter(MethodInfo method)
{
return method.IsSpecialName && method.Name.StartsWith("get_", StringComparison.Ordinal);
}
private bool IsSetter(MethodInfo method)
{
return method.IsSpecialName && method.Name.StartsWith("set_", StringComparison.Ordinal);
}
}
[Serializable]
class GameModeInterceptor : IInterceptor
{
@@ -22,6 +48,7 @@ namespace Nexus.Client.CLI
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
if (invocation.Method.Name == "get_WritablePaths")
{
IEnumerable<string> temp = (IEnumerable<string>)invocation.ReturnValue;
+8 -5
View File
@@ -15,7 +15,6 @@
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<IsWebBootstrapper>false</IsWebBootstrapper>
<NoWin32Manifest>False</NoWin32Manifest>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib>
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
@@ -139,7 +138,7 @@
<PlatformTarget>x86</PlatformTarget>
<DebugType>PdbOnly</DebugType>
<Optimize>True</Optimize>
<OutputPath>..\bin\Release\</OutputPath>
<OutputPath>..\nmm\bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@@ -151,6 +150,9 @@
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="Castle.Core">
<HintPath>.\Castle.Core.dll</HintPath>
@@ -170,7 +172,6 @@
</ItemGroup>
<ItemGroup>
<Compile Include="GameModeInterceptor.cs" />
<Compile Include="GameModeWrapper.cs" />
<Compile Include="DummyDataFileUtilFactory.cs" />
<Compile Include="Logger.cs" />
<Compile Include="DummyDataFileUtil.cs" />
@@ -181,7 +182,6 @@
<Compile Include="ModManagement\IniMethods.cs" />
<Compile Include="ModManagement\ModExtension.cs" />
<Compile Include="ModManagement\ModFileInstaller.cs" />
<Compile Include="ModManagement\Scripting\IScriptExtensions.cs" />
<Compile Include="Mods\NexusModCacheManager.cs" />
<Compile Include="Pair.cs" />
<Compile Include="Program.cs" />
@@ -198,6 +198,7 @@
<None Include="app.config">
<SubType>Designer</SubType>
</None>
<None Include="app.manifest" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
@@ -259,7 +260,9 @@
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Folder Include="ModManagement\Scripting\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
+11 -14
View File
@@ -158,19 +158,6 @@ namespace Nexus.Client.CLI
IGameMode gameMode = gameModeFactory.BuildGameMode(fileUtil, out warning);
// use a proxy so we can intercept accesses to the IGameMode interface. This allows us to make the additional search paths accessible from
// the sandbox and feed in the script extender version even though the nmm lib won't find it.
// This is a massive hack and there is an issue: nmm tries to look up the location of the assembly (for whatever reason) and the proxy
// generated here is in a dynamic assembly and thus doesn't have a location. We will therefore feed the proxy only to the script executor
// and hope for the best
ProxyGenerator generator = new ProxyGenerator();
GameModeInterceptor interceptor = new GameModeInterceptor(additionalSearchPaths, seVersion != null ? new Version(seVersion) : null);
IGameMode gameModeProxied = (IGameMode)generator.CreateClassProxyWithTarget(gameMode.GetType(),
gameMode,
new object[] { environmentInfo, fileUtil },
new IInterceptor[] { interceptor });
IModCacheManager cacheManager = new NexusModCacheManager(environmentInfo.TemporaryPath, gameMode.GameModeEnvironmentInfo.ModDirectory, fileUtil);
IScriptTypeRegistry scriptTypeRegistry = ScriptTypeRegistry.DiscoverScriptTypes(Path.Combine(Path.GetDirectoryName(exeLocation), "ScriptTypes"), gameMode);
@@ -180,6 +167,16 @@ namespace Nexus.Client.CLI
return 2;
}
// use a proxy so we can intercept accesses to the IGameMode interface. This allows us to make the additional search paths accessible from
// the sandbox and feed in the script extender version even though the nmm lib won't find it.
// This has to happen after DiscoverScriptTypes becaus that function tries to localize the assembly which fails for the dynamic assembly
// of the proxy. Fortunately DiscoverScriptTypes has no side-effects on the gameMode.
// This recreates the gamemode object so it's important no code above modifies gameMode
ProxyGenerator generator = new ProxyGenerator();
GameModeInterceptor interceptor = new GameModeInterceptor(additionalSearchPaths, seVersion != null ? new Version(seVersion) : null);
gameMode = (IGameMode)generator.CreateClassProxy(gameMode.GetType(), new object[] { environmentInfo, fileUtil }, new IInterceptor[] { interceptor });
IModFormatRegistry formatRegistry = ModFormatRegistry.DiscoverFormats(cacheManager, scriptTypeRegistry, Path.Combine(Path.GetDirectoryName(exeLocation), "ModFormats"));
if (formatRegistry.Formats.Count == 0)
{
@@ -220,7 +217,7 @@ namespace Nexus.Client.CLI
IGameSpecificValueInstaller gameSpecificValueInstaller = gameMode.GetGameSpecificValueInstaller(mod, installLog, fileManager, new NexusFileUtil(environmentInfo), delegate { return OverwriteResult.No; });
IModFileInstaller fileInstaller = new ModFileInstaller(gameMode.GameModeEnvironmentInfo, mod, installLog, pluginManager, dataFileUtility, fileManager, delegate { return OverwriteResult.No; }, false);
InstallerGroup installers = new InstallerGroup(dataFileUtility, fileInstaller, iniIniInstaller, gameSpecificValueInstaller, pluginManager);
IScriptExecutor executor = mod.InstallScript.Type.CreateExecutor(mod, gameModeProxied, environmentInfo, installers, SynchronizationContext.Current);
IScriptExecutor executor = mod.InstallScript.Type.CreateExecutor(mod, gameMode, environmentInfo, installers, SynchronizationContext.Current);
// read-only transactions are waaaay faster, especially for solid archives) because the extractor isn't recreated for every extraction (why exactly would it be otherwise?)
mod.BeginReadOnlyTransaction(fileUtil);
// run the script in a second thread and start the main loop in the main thread to ensure we can handle message boxes and the like
+2 -2
View File
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18444
// Runtime Version:4.0.30319.34014
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -12,7 +12,7 @@ namespace Nexus.Client.CLI.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+3 -3
View File
@@ -109,6 +109,9 @@
<setting name="UseMultithreadedDownloads" serializeAs="String">
<value>False</value>
</setting>
<setting name="ShowStartupMessage" serializeAs="String">
<value>False</value>
</setting>
<setting name="InstallationPaths" serializeAs="Xml">
<value>
<PerGameModeSettingsOfString/>
@@ -184,9 +187,6 @@
<PerGameModeSettingsOfKeyedSettingsOfString/>
</value>
</setting>
<setting name="ShowStartupMessage" serializeAs="String">
<value>False</value>
</setting>
</Nexus.Client.CLI.Properties.Settings>
</userSettings>
<applicationSettings>
+58
View File
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Specifying requestedExecutionLevel node will disable file and registry virtualization.
If you want to utilize File and Registry Virtualization for backward
compatibility then delete the requestedExecutionLevel node.
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of all Windows versions that this application is designed to work with.
Windows will automatically select the most compatible environment.-->
<!-- If your application is designed to work with Windows Vista, uncomment the following supportedOS node-->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>-->
<!-- If your application is designed to work with Windows 7, uncomment the following supportedOS node-->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>-->
<!-- If your application is designed to work with Windows 8, uncomment the following supportedOS node-->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>-->
<!-- If your application is designed to work with Windows 8.1, uncomment the following supportedOS node-->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>-->
</application>
</compatibility>
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</asmv1:assembly>