Skip to content

Implement ExtraVFS for extended VFS usage such as redirecting savegames #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions EntryPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Threading;
using Andraste.Payload.ExtraVFS;
using Andraste.Payload.ModManagement;
using Andraste.Payload.Native;
using Andraste.Shared.Lifecycle;
Expand Down Expand Up @@ -52,13 +53,15 @@ public abstract class EntryPoint : IEntryPoint
protected readonly Dictionary<string, IFeatureParser> FeatureParser = new Dictionary<string, IFeatureParser>();
public readonly ManagerContainer Container;
private readonly ModLoader _modLoader;
private readonly ExtraVFSLoader _extraVFSLoader;

protected EntryPoint(RemoteHooking.IContext context)
{
GameFolder = Directory.GetCurrentDirectory();
ModFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
Container = new ManagerContainer();
_modLoader = new ModLoader(this);
_extraVFSLoader = new ExtraVFSLoader(this);
}

public virtual void Run(RemoteHooking.IContext context)
Expand Down Expand Up @@ -91,7 +94,9 @@ public virtual void Run(RemoteHooking.IContext context)

Logger.Trace("Implementing Mods");
ImplementMods();


ImplementExtraVFS();

Logger.Trace("Waking up the Application");
RemoteHooking.WakeUpProcess();
Logger.Trace("Calling Post-Wakeup");
Expand Down Expand Up @@ -189,7 +194,14 @@ protected virtual void LoadFeatureParsers()
FeatureParser.Add("andraste.builtin.plugin", new PluginFeatureParser());
}
#endregion


#region ExtraVFS
protected virtual void ImplementExtraVFS()
{
_extraVFSLoader.LoadExtraVFSFromJson(ModFolder);
}
#endregion

#region Lifecycle
/// <summary>
/// This is called when Andraste has been loaded so far and the user
Expand Down
98 changes: 98 additions & 0 deletions ExtraVFS/ExtraVFSLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using Andraste.Payload.VFS;
using System;
using System.IO;
using System.Text.Json;
using NLog;

namespace Andraste.Payload.ExtraVFS
{
public class ExtraVFSPairs
{
public ExtraVFSPair[] PathPairs { get; set; }
}
public class ExtraVFSPair
{
public string Source { get; set; }
public string Dest { get; set; }
public bool DestHasToExist { get; set; }
}
public class ExtraVFSLoader
{
private EntryPoint _entryPoint;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

public ExtraVFSLoader(EntryPoint entryPoint)
{
_entryPoint = entryPoint;
}

public void LoadExtraVFSFromJson(string modFolder)
{
var vfs = _entryPoint.Container.GetManager<BasicFileRedirectingManager>();
if (vfs != null)
{
var jsonFile = Path.Combine(modFolder, "extra_vfs.json");
if (!File.Exists(jsonFile))
{
var empty_template = new ExtraVFSPairs();
empty_template.PathPairs = new ExtraVFSPair[1];
empty_template.PathPairs[0] = new ExtraVFSPair();
empty_template.PathPairs[0].Source = "C:\\Some\\Savegame\\Path";
empty_template.PathPairs[0].Dest = "C:\\Some\\Savegame\\Path";
empty_template.PathPairs[0].DestHasToExist = false;
var empty_template_string = JsonSerializer.SerializeToUtf8Bytes(empty_template, new JsonSerializerOptions { WriteIndented = true});
try
{
File.WriteAllBytes(jsonFile, empty_template_string);
}
catch(Exception ex)
{
Logger.Warn("Couldn't create template extra_vfs.json, " + ex);
}
}

try
{
var pairs = JsonSerializer.Deserialize<ExtraVFSPairs>(File.ReadAllText(jsonFile));
if (pairs == null)
{
Logger.Warn("Couldn't properly parse extra_vfs.json");
return;
}

if (pairs.PathPairs == null)
{
return;
}

foreach (var pair in pairs.PathPairs)
{
if (!Directory.Exists(pair.Dest) && pair.DestHasToExist)
{
try
{
Directory.CreateDirectory(pair.Dest);
}
catch (Exception ex)
{
Logger.Error("Destination " + pair.Dest + " does not exist and cannot be created, " + ex);
throw ex;
}
}
Logger.Trace("adding pair " + pair.Source + ", " + pair.Dest);
vfs.AddPrefixMapping(pair.Source.Replace('/', '\\'), pair.Dest.Replace('/', '\\'));
}
}
catch(Exception ex)
{
Logger.Warn("ExtraVFS: Couldn't properly parse extra_vfs.json, " + ex);
}
return;
}
else
{
Logger.Info($"The Framework {_entryPoint.FrameworkName} has not enabled VFS Features");
}
}
}
}
17 changes: 16 additions & 1 deletion Native/Kernel32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,22 @@ public static extern IntPtr CreateFileA(string lpFileName, uint dwDesiredAccess,
public delegate IntPtr Delegate_CreateFileA(string lpFileName, uint dwDesiredAccess,
uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
uint dwFlagsAndAttributes, IntPtr hTemplateFile);


[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
public static extern bool CreateDirectoryA(string lpFileName, IntPtr lpSecurityAttributes);

public delegate bool Delegate_CreateDirectoryA(string lpFileName, IntPtr lpSecurityAttribute);

[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
public static extern bool DeleteFileA(string lpFileName);

public delegate bool Delegate_DeleteFileA(string lpFileName);

[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
public static extern bool RemoveDirectoryA(string lpFileName);

public delegate bool Delegate_RemoveDirectoryA(string lpFileName);

[DllImport("kernel32.dll")]
public static extern bool VirtualProtect(IntPtr lpAddress, IntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);

Expand Down
12 changes: 12 additions & 0 deletions Native/Shell32.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;
using System.Runtime.InteropServices;

namespace Andraste.Payload.Native
{
public static class Shell32
{
[DllImport("shell32.dll", CharSet = CharSet.Ansi)]
public static extern int SHFileOperationA(IntPtr lpFileOp);
public delegate int Delegate_SHFileOperationA(IntPtr lpFileOp);
}
}
Loading