Compare commits

...
Author SHA1 Message Date
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
3 changed files with 44 additions and 15 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;
+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