1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Cleaned up resources

Fixed pipe server keeping Artemis from shutting down
Pipe server no longer quietly fails (should hopefully give some insight on Overwatch issues)
Added UT folder selection and auto-detection
This commit is contained in:
SpoinkyNL 2016-08-12 20:06:30 +02:00
parent 63b0b1d8e5
commit aa10b20759
14 changed files with 186 additions and 112 deletions

View File

@ -629,10 +629,12 @@
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<EmbeddedResource Include="Modules\Games\UnrealTournament\Resources\ut-plugin.zip" />
<None Include="Modules\Games\UnrealTournament\UnrealTournament.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>UnrealTournament.Designer.cs</LastGenOutput>
</None>
<EmbeddedResource Include="Modules\Games\Witcher3\Resources\witcher3-mod.zip" />
<None Include="Modules\Games\WorldofWarcraft\WoW.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>WoW.Designer.cs</LastGenOutput>
@ -716,7 +718,6 @@
<Resource Include="Resources\Keyboards\blackwidow.png" />
<None Include="Resources\Keyboards\none.png" />
<None Include="Resources\Keyboards\demo-gif.gif" />
<EmbeddedResource Include="Resources\Witcher3\Witcher3Artemis.zip" />
<None Include="Settings\Offsets.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Offsets.Designer.cs</LastGenOutput>

View File

@ -25,8 +25,8 @@ namespace Artemis.Managers
private readonly IEventAggregator _events;
private readonly Timer _processTimer;
public MainManager(IEventAggregator events, ILogger logger, LoopManager loopManager,
DeviceManager deviceManager, EffectManager effectManager, ProfileManager profileManager)
public MainManager(IEventAggregator events, ILogger logger, LoopManager loopManager, DeviceManager deviceManager,
EffectManager effectManager, ProfileManager profileManager, PipeServer pipeServer)
{
_events = events;
@ -35,6 +35,7 @@ namespace Artemis.Managers
DeviceManager = deviceManager;
EffectManager = effectManager;
ProfileManager = profileManager;
PipeServer = pipeServer;
_processTimer = new Timer(1000);
_processTimer.Elapsed += ScanProcesses;
@ -48,7 +49,6 @@ namespace Artemis.Managers
GameStateWebServer.Start();
// Start the named pipe
PipeServer = new PipeServer();
PipeServer.Start("artemis");
Logger.Info("Intialized MainManager");

View File

@ -17,8 +17,8 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,1,0">
<Label FontSize="20" HorizontalAlignment="Left">
<Label.Content>
@ -35,6 +35,7 @@
</StackPanel>
</StackPanel>
<!-- Game directory -->
<StackPanel Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2" Margin="0,0,1,0">

View File

@ -9,16 +9,20 @@ namespace Artemis.Modules.Games.UnrealTournament
Load();
}
public string GameDirectory { get; set; }
public sealed override void Load()
{
Enabled = UnrealTournament.Default.Enabled;
LastProfile = UnrealTournament.Default.LastProfile;
GameDirectory = UnrealTournament.Default.GameDirectory;
}
public sealed override void Save()
{
UnrealTournament.Default.Enabled = Enabled;
UnrealTournament.Default.LastProfile = LastProfile;
UnrealTournament.Default.GameDirectory = GameDirectory;
UnrealTournament.Default.Save();
}
@ -26,6 +30,7 @@ namespace Artemis.Modules.Games.UnrealTournament
public sealed override void ToDefault()
{
Enabled = true;
GameDirectory = string.Empty;
}
}
}

View File

@ -15,15 +15,12 @@
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,1,0">
<Label FontSize="20" HorizontalAlignment="Left">
<Label.Content>
@ -40,11 +37,27 @@
</StackPanel>
</StackPanel>
<!-- Game directory -->
<StackPanel Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2" Margin="0,0,1,0">
<Label FontSize="20" HorizontalAlignment="Left" Content="Unreal Tournament Directory" />
<Grid>
<TextBox x:Name="GameDirectory" Height="23" TextWrapping="Wrap" Margin="5,0,30,0"
Text="{Binding Path=GameSettings.GameDirectory, Mode=TwoWay}"
cal:Message.Attach="[Event LostFocus] = [Action PlaceFiles]" />
<Button x:Name="BrowseDirectory" Content="..." RenderTransformOrigin="-0.039,-0.944"
HorizontalAlignment="Right" Width="25"
Style="{DynamicResource SquareButtonStyle}" Height="26" Margin="0,-2,0,0" />
</Grid>
</StackPanel>
<!-- Profile editor -->
<ContentControl Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" Margin="0,0,-30,0" />
<ContentControl Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" x:Name="ProfileEditor" Margin="0,0,-30,0" />
<!-- Buttons -->
<StackPanel Grid.Column="0" Grid.Row="9" Orientation="Horizontal" VerticalAlignment="Bottom">
<StackPanel Grid.Column="0" Grid.Row="3" Orientation="Horizontal" VerticalAlignment="Bottom">
<Button x:Name="ResetSettings" Content="Reset effect" VerticalAlignment="Top" Width="100"
Style="{DynamicResource SquareButtonStyle}" />
<Button x:Name="SaveSettings" Content="Save changes" VerticalAlignment="Top" Width="100"

View File

@ -1,33 +1,116 @@
using Artemis.InjectionFactories;
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Artemis.InjectionFactories;
using Artemis.Managers;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract;
using Caliburn.Micro;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Artemis.Modules.Games.UnrealTournament
{
public sealed class UnrealTournamentViewModel : GameViewModel
{
private string _versionText;
public UnrealTournamentViewModel(MainManager main, IEventAggregator events, IProfileEditorVmFactory pFactory)
: base(main, new UnrealTournamentModel(main, new UnrealTournamentSettings()), events, pFactory)
{
DisplayName = "Unreal Tournament";
MainManager.EffectManager.EffectModels.Add(GameModel);
}
public string VersionText
{
get { return _versionText; }
set
{
if (value == _versionText) return;
_versionText = value;
NotifyOfPropertyChange(() => VersionText);
}
FindGame();
}
public UnrealTournamentModel UnrealTournamentModel { get; set; }
public void FindGame()
{
var gameSettings = (UnrealTournamentSettings) GameSettings;
// If already propertly set up, don't do anything
if (gameSettings.GameDirectory != null && File.Exists(gameSettings.GameDirectory + "UE4-Win64-Shipping.exe"))
return;
// Attempt to read the file
if (!File.Exists(@"C:\ProgramData\Epic\UnrealEngineLauncher\LauncherInstalled.dat"))
return;
var json =
JsonConvert.DeserializeObject<JObject>(
File.ReadAllText(@"C:\ProgramData\Epic\UnrealEngineLauncher\LauncherInstalled.dat"));
var utEntry =
json["InstallationList"].Children()
.FirstOrDefault(c => c["AppName"].Value<string>() == "UnrealTournamentDev");
if (utEntry == null)
return;
var utDir = utEntry["InstallLocation"].Value<string>();
// Use backslash in path for consistency
utDir = utDir.Replace('/', '\\');
if (!File.Exists(utDir + @"\UE4-Win64-Shipping.exe"))
return;
gameSettings.GameDirectory = utDir;
gameSettings.Save();
PlaceFiles();
}
public void BrowseDirectory()
{
var dialog = new FolderBrowserDialog
{
SelectedPath = ((UnrealTournamentSettings) GameSettings).GameDirectory
};
var result = dialog.ShowDialog();
if (result != DialogResult.OK)
return;
((UnrealTournamentSettings) GameSettings).GameDirectory = dialog.SelectedPath;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
PlaceFiles();
}
public void PlaceFiles()
{
var path = ((UnrealTournamentSettings) GameSettings).GameDirectory;
if (!File.Exists(path + @"\UE4-Win64-Shipping.exe"))
{
DialogService.ShowErrorMessageBox("Please select a valid Unreal Tournament directory\n\n" +
@"By default Unreal Tournament is in C:\Program Files\Epic Games\UnrealTournament");
((UnrealTournamentSettings) GameSettings).GameDirectory = string.Empty;
NotifyOfPropertyChange(() => GameSettings);
GameSettings.Save();
MainManager.Logger.Warn("Failed to install Unreal Tournament plugin in '{0}' (path not found)", path);
return;
}
// Load the ZIP from resources
var stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("Artemis.Modules.Games.UnrealTournament.Resources.ut-plugin.zip");
if (stream == null)
throw new FileNotFoundException("Couldn't load the UT plugin files from resources.");
var archive = new ZipArchive(stream);
try
{
Directory.CreateDirectory(path + @"\UnrealTournament\Plugins\Artemis");
archive.ExtractToDirectory(path + @"\UnrealTournament\Plugins\Artemis", true);
}
catch (Exception e)
{
MainManager.Logger.Error(e, "Failed to install Unreal Tournament plugin in '{0}'", path);
return;
}
MainManager.Logger.Info("Installed Unreal Tournament plugin in '{0}'", path);
}
}
}

View File

@ -50,7 +50,7 @@ namespace Artemis.Modules.Games.Witcher3
// Load the ZIP from resources
var stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("Artemis.Resources.Witcher3.Witcher3Artemis.zip");
.GetManifestResourceStream("Artemis.Modules.Games.Witcher3.Resources.witcher3-mod.zip");
if (stream == null)
throw new FileNotFoundException("Couldn't load the Witcher 3 mod files from resources.");
var archive = new ZipArchive(stream);

View File

@ -311,9 +311,19 @@ namespace Artemis.Properties {
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] Witcher3Artemis {
internal static byte[] ut_plugin {
get {
object obj = ResourceManager.GetObject("Witcher3Artemis", resourceCulture);
object obj = ResourceManager.GetObject("ut_plugin", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] witcher3_mod {
get {
object obj = ResourceManager.GetObject("witcher3_mod", resourceCulture);
return ((byte[])(obj));
}
}

View File

@ -178,13 +178,16 @@
<data name="demo_gif" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Keyboards\demo-gif.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Witcher3Artemis" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Witcher3\Witcher3Artemis.zip;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="g810" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Keyboards\g810.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="generic" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\generic.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ut_plugin" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Modules\Games\UnrealTournament\Resources\ut-plugin.zip;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="witcher3_mod" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Modules\Games\Witcher3\Resources\witcher3-mod.zip;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

View File

@ -1,10 +1,10 @@
using System;
using System.Diagnostics;
using System.IO.Pipes;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using Ninject.Extensions.Logging;
namespace Artemis.Utilities.DataReaders
{
@ -13,80 +13,34 @@ namespace Artemis.Utilities.DataReaders
public class PipeServer
{
private readonly ILogger _logger;
private string _pipeName;
public bool Running { get; set; }
private NamedPipeServerStream _pipeServer;
public event DelegateMessage PipeMessage;
public PipeServer(ILogger logger)
{
_logger = logger;
}
public void Start(string pipeName)
{
Running = true;
_pipeName = pipeName;
var task = new Task(PipeLoop);
task.Start();
var security = new PipeSecurity();
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl, AccessControlType.Allow));
_pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In, 254,
PipeTransmissionMode.Byte, PipeOptions.Asynchronous, 4096, 4096, security);
_pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, _pipeServer);
_logger.Info("Opened named pipe '{0}'", _pipeName);
}
public void Stop()
{
Running = false;
}
private void PipeLoop()
{
try
{
var security = new PipeSecurity();
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl,
AccessControlType.Allow));
while (Running)
{
var namedPipeServerStream = new NamedPipeServerStream(_pipeName, PipeDirection.In, 254,
PipeTransmissionMode.Byte, PipeOptions.None, 4096, 4096, security);
namedPipeServerStream.WaitForConnection();
var buffer = new byte[4096];
namedPipeServerStream.Read(buffer, 0, 4096);
namedPipeServerStream.Close();
var task = new Task(() => HandleMessage(buffer));
task.Start();
}
}
catch
{
// ignored
}
}
private void HandleMessage(byte[] buffer)
{
var request = Encoding.ASCII.GetString(buffer);
PipeMessage?.Invoke(request);
}
public void Listen(string pipeName)
{
try
{
var security = new PipeSecurity();
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl, AccessControlType.Allow));
// Set to class level var so we can re-use in the async callback method
_pipeName = pipeName;
// Create the new async pipe
var pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.In, 254, PipeTransmissionMode.Byte,
PipeOptions.Asynchronous, 254, 254, security);
// Wait for a connection
pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, pipeServer);
}
catch (Exception oEx)
{
Debug.WriteLine(oEx.Message);
}
_pipeServer.Close();
_pipeServer.Dispose();
_logger.Info("Closed named pipe '{0}'", _pipeName);
}
private void WaitForConnectionCallBack(IAsyncResult iar)
@ -98,34 +52,39 @@ namespace Artemis.Utilities.DataReaders
// End waiting for the connection
pipeServer.EndWaitForConnection(iar);
var buffer = new byte[255];
var buffer = new byte[4096];
// Read the incoming message
pipeServer.Read(buffer, 0, 255);
// Convert byte buffer to string
var stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
var stringData = Encoding.ASCII.GetString(buffer, 0, buffer.Length);
// Pass message back to calling form
PipeMessage?.Invoke(stringData);
// Kill original sever and create new wait server
pipeServer.Close();
var security = new PipeSecurity();
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl, AccessControlType.Allow));
pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In, 254, PipeTransmissionMode.Byte,
PipeOptions.Asynchronous, 254, 254, security);
pipeServer = GetPipeServer(_pipeName);
// Recursively wait for the connection again and again....
_pipeServer = pipeServer;
pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, pipeServer);
}
catch
catch (Exception e)
{
_logger.Error(e, "Exception in named pipe '{0}'", _pipeName);
// ignored
}
}
private static NamedPipeServerStream GetPipeServer(string name)
{
var security = new PipeSecurity();
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
security.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl, AccessControlType.Allow));
return new NamedPipeServerStream(name, PipeDirection.In, 254, PipeTransmissionMode.Byte,
PipeOptions.Asynchronous, 4096, 4096, security);
}
}
}

View File

@ -33,12 +33,11 @@ namespace Artemis.Utilities
foreach (var file in archive.Entries)
{
var completeFileName = Path.Combine(destinationDirectoryName, file.FullName);
Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
if (file.Name == "")
{
// Assuming Empty for Directory
Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
continue;
}
file.ExtractToFile(completeFileName, true);
}
}

Binary file not shown.