diff --git a/Artemis/Artemis.sln b/Artemis/Artemis.sln
index 6c8abbab3..0e9c57ea1 100644
--- a/Artemis/Artemis.sln
+++ b/Artemis/Artemis.sln
@@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis", "Artemis\Artemis.
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Razer2Artemis", "Razer2Artemis\Razer2Artemis.vcxproj", "{39711909-C1D5-46CE-A9EA-2D561692EA47}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnrealTournament2Artemis", "UnrealTournament2Artemis\UnrealTournament2Artemis.vcxproj", "{3541864F-1662-4BD6-8328-2C87AE61D152}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CD_ROM|Any CPU = CD_ROM|Any CPU
@@ -84,6 +86,34 @@ Global
{39711909-C1D5-46CE-A9EA-2D561692EA47}.SingleImage|x64.Build.0 = Release|x64
{39711909-C1D5-46CE-A9EA-2D561692EA47}.SingleImage|x86.ActiveCfg = Release|Win32
{39711909-C1D5-46CE-A9EA-2D561692EA47}.SingleImage|x86.Build.0 = Release|Win32
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.CD_ROM|Any CPU.ActiveCfg = Release|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.CD_ROM|Any CPU.Build.0 = Release|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.CD_ROM|x64.ActiveCfg = Release|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.CD_ROM|x64.Build.0 = Release|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.CD_ROM|x86.ActiveCfg = Release|Win32
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.CD_ROM|x86.Build.0 = Release|Win32
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.Debug|x64.ActiveCfg = Debug|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.Debug|x64.Build.0 = Debug|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.Debug|x86.ActiveCfg = Debug|Win32
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.Debug|x86.Build.0 = Debug|Win32
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.DVD-5|Any CPU.ActiveCfg = Release|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.DVD-5|Any CPU.Build.0 = Release|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.DVD-5|x64.ActiveCfg = Debug|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.DVD-5|x64.Build.0 = Debug|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.DVD-5|x86.ActiveCfg = Debug|Win32
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.DVD-5|x86.Build.0 = Debug|Win32
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.Release|Any CPU.ActiveCfg = Release|Win32
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.Release|x64.ActiveCfg = Release|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.Release|x64.Build.0 = Release|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.Release|x86.ActiveCfg = Release|Win32
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.Release|x86.Build.0 = Release|Win32
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|Any CPU.ActiveCfg = Release|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|Any CPU.Build.0 = Release|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|x64.ActiveCfg = Release|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|x64.Build.0 = Release|x64
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|x86.ActiveCfg = Release|Win32
+ {3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Artemis/Artemis/App.config b/Artemis/Artemis/App.config
index 62b94b3c1..af9997c3f 100644
--- a/Artemis/Artemis/App.config
+++ b/Artemis/Artemis/App.config
@@ -1,7 +1,9 @@
+
+
@@ -27,6 +29,17 @@
+
+
+ True
+
+
+ Default
+
+
+
+
+
True
@@ -278,7 +291,7 @@
-
+
@@ -311,4 +324,4 @@
-
+
\ No newline at end of file
diff --git a/Artemis/Artemis/App.xaml.cs b/Artemis/Artemis/App.xaml.cs
index 008f21c59..7b5f4dc88 100644
--- a/Artemis/Artemis/App.xaml.cs
+++ b/Artemis/Artemis/App.xaml.cs
@@ -13,6 +13,12 @@ namespace Artemis
///
public partial class App : Application
{
+ protected override void OnExit(ExitEventArgs e)
+ {
+ base.OnExit(e);
+ Environment.Exit(0);
+ }
+
public App()
{
if (!IsRunAsAdministrator())
@@ -31,11 +37,6 @@ namespace Artemis
return wp.IsInRole(WindowsBuiltInRole.Administrator);
}
- private void Application_Startup(object sender, StartupEventArgs e)
- {
- AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
- }
-
private void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
if (DoHandle)
@@ -50,12 +51,6 @@ namespace Artemis
}
}
- private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
- {
- var ex = e.ExceptionObject as Exception;
- GetArtemisExceptionViewer(ex).ShowDialog();
- }
-
private static ExceptionViewer GetArtemisExceptionViewer(Exception e)
{
var logger = LogManager.GetCurrentClassLogger();
diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj
index 0016043d5..707d8f05a 100644
--- a/Artemis/Artemis/Artemis.csproj
+++ b/Artemis/Artemis/Artemis.csproj
@@ -40,7 +40,7 @@
Artemis
Artemis
0
- 1.2.2.0
+ 1.2.3.0
false
true
true
@@ -141,8 +141,8 @@
False
lib\ColorBox.dll
-
- ..\packages\Colore.4.0.0\lib\net35\Corale.Colore.dll
+
+ ..\packages\Colore.5.0.0\lib\net35\Corale.Colore.dll
True
@@ -176,8 +176,8 @@
..\packages\NAudio.1.7.3\lib\net35\NAudio.dll
True
-
- ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll
+
+ ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
True
@@ -197,7 +197,7 @@
True
- ..\packages\NLog.4.3.4\lib\net45\NLog.dll
+ ..\packages\NLog.4.3.7\lib\net45\NLog.dll
True
@@ -205,7 +205,7 @@
D:\Downloads\Chome Downloads\Process.NET-master\Process.NET-master\src\Process.NET\bin\Release\Process.NET.dll
- ..\packages\SpotifyAPI-NET.2.9.0\lib\SpotifyAPI.dll
+ ..\packages\SpotifyAPI-NET.2.11.0\lib\SpotifyAPI.dll
True
@@ -312,6 +312,18 @@
+
+ True
+ True
+ UnrealTournament.settings
+
+
+
+
+
+ UnrealTournamentView.xaml
+
+
True
True
@@ -617,10 +629,19 @@
Code
+
+
+ SettingsSingleFileGenerator
+ UnrealTournament.Designer.cs
+
+
SettingsSingleFileGenerator
WoW.Designer.cs
+
+ Designer
+
@@ -668,9 +689,6 @@
SettingsSingleFileGenerator
VolumeDisplay.Designer.cs
-
- Designer
-
Designer
@@ -700,7 +718,6 @@
-
SettingsSingleFileGenerator
Offsets.Designer.cs
@@ -732,6 +749,10 @@
Designer
MSBuild:Compile
+
+ MSBuild:Compile
+ Designer
+
MSBuild:Compile
Designer
@@ -857,6 +878,7 @@
PreserveNewest
+
diff --git a/Artemis/Artemis/ArtemisBootstrapper.cs b/Artemis/Artemis/ArtemisBootstrapper.cs
index d0aec9007..2b67e8842 100644
--- a/Artemis/Artemis/ArtemisBootstrapper.cs
+++ b/Artemis/Artemis/ArtemisBootstrapper.cs
@@ -95,6 +95,7 @@ namespace Artemis
protected override void OnExit(object sender, EventArgs e)
{
_kernel.Dispose();
+// Enviroment.Exit(0);
base.OnExit(sender, e);
}
diff --git a/Artemis/Artemis/DAL/ProfileProvider.cs b/Artemis/Artemis/DAL/ProfileProvider.cs
index 2e5aae995..0af504d90 100644
--- a/Artemis/Artemis/DAL/ProfileProvider.cs
+++ b/Artemis/Artemis/DAL/ProfileProvider.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
@@ -19,9 +20,10 @@ namespace Artemis.DAL
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
- private static readonly string ProfileFolder = Environment
- .GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles";
+ private static readonly string ProfileFolder =
+ Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles";
+ private static readonly List Profiles = new List();
private static bool _installedDefaults;
///
@@ -30,7 +32,15 @@ namespace Artemis.DAL
/// All profiles
public static List GetAll()
{
- return ReadProfiles();
+ lock (Profiles)
+ {
+ if (!Profiles.Any())
+ ReadProfiles();
+
+ // Return a new list, this'll make sure removing/updating the retrieved list doesn't
+ // affect the datastore
+ return Profiles.ToList();
+ }
}
///
@@ -59,8 +69,15 @@ namespace Artemis.DAL
if (prof == null)
throw new ArgumentNullException(nameof(prof));
+ lock (Profiles)
+ {
+ if (!Profiles.Contains(prof))
+ Profiles.Add(prof);
+ }
+
lock (prof)
{
+ // Store the file
if (!(prof.GameName?.Length > 1) || !(prof.KeyboardSlug?.Length > 1) || !(prof.Name?.Length > 1))
throw new ArgumentException("Profile is invalid. Name, GameName and KeyboardSlug are required");
@@ -86,31 +103,43 @@ namespace Artemis.DAL
}
}
- private static List ReadProfiles()
+ private static void ReadProfiles()
{
CheckProfiles();
- InstallDefaults();
- var profiles = new List();
-
- // Create the directory structure
- var profilePaths = Directory.GetFiles(ProfileFolder, "*.json", SearchOption.AllDirectories);
-
- // Parse the JSON files into objects and add them if they are valid
- foreach (var path in profilePaths)
+ lock (Profiles)
{
- try
+ Profiles.Clear();
+
+ // Create the directory structure
+ var profilePaths = Directory.GetFiles(ProfileFolder, "*.json", SearchOption.AllDirectories);
+
+ // Parse the JSON files into objects and add them if they are valid
+ foreach (var path in profilePaths)
{
- var prof = LoadProfileIfValid(path);
- if (prof != null)
- profiles.Add(prof);
- }
- catch (Exception e)
- {
- Logger.Error("Failed to load profile: {0} - {1}", path, e.InnerException.Message);
+ try
+ {
+ var prof = LoadProfileIfValid(path);
+ if (prof == null)
+ continue;
+
+ // Only add unique profiles
+ if (Profiles.Any(p => p.GameName == prof.GameName && p.Name == prof.Name &&
+ p.KeyboardSlug == prof.KeyboardSlug))
+ {
+ Logger.Error("Didn't load duplicate profile: {0}", path);
+ }
+ else
+ {
+ Profiles.Add(prof);
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Error("Failed to load profile: {0} - {1}", path, e.InnerException.Message);
+ }
}
}
-
- return profiles;
+ InstallDefaults();
}
///
@@ -133,23 +162,27 @@ namespace Artemis.DAL
var archive = new ZipArchive(stream);
archive.ExtractToDirectory(ProfileFolder, true);
- // Extract the demo GIF file
- var gifPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\demo-gif.gif";
- Resources.demo_gif.Save(gifPath);
+ var demoProfiles = Profiles.Where(d => d.Name == "Demo (duplicate to keep changes)");
+ InsertGif(demoProfiles, "GIF", Resources.demo_gif, "demo-gif");
+ }
- // Set the GIF path on each demo profile
- var demoProfiles = GetAll().Where(d => d.Name == "Demo (Duplicate to keep changes)");
- foreach (var demoProfile in demoProfiles)
+ public static void InsertGif(IEnumerable profileModels, string layerName, Bitmap gifFile,
+ string fileName)
+ {
+ // Extract the GIF file
+ var gifDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\gifs";
+ Directory.CreateDirectory(gifDir);
+ var gifPath = gifDir + $"\\{fileName}.gif";
+ gifFile.Save(gifPath);
+
+ foreach (var profile in profileModels)
{
- var gifLayer = demoProfile
- .Layers.FirstOrDefault(l => l.Name == "Demo - GIFs")?
- .Children.FirstOrDefault(c => c.Name == "GIF");
-
+ var gifLayer = profile.GetLayers().FirstOrDefault(l => l.Name == layerName);
if (gifLayer == null)
continue;
((KeyboardPropertiesModel) gifLayer.Properties).GifFile = gifPath;
- AddOrUpdate(demoProfile);
+ AddOrUpdate(profile);
}
}
@@ -172,7 +205,6 @@ namespace Artemis.DAL
/// The loaded profile, or null if invalid
public static ProfileModel LoadProfileIfValid(string path)
{
- // TODO: What exception on load failure?
try
{
var prof = JsonConvert.DeserializeObject(File.ReadAllText(path));
@@ -182,7 +214,7 @@ namespace Artemis.DAL
return null;
return prof;
}
- catch (Exception)
+ catch (JsonSerializationException)
{
return null;
}
@@ -209,20 +241,29 @@ namespace Artemis.DAL
if (string.IsNullOrEmpty(name))
return;
- // Remove the old file
- var path = ProfileFolder + $@"\{profile.KeyboardSlug}\{profile.GameName}\{profile.Name}.json";
- if (File.Exists(path))
- File.Delete(path);
+ // Remove the old profile
+ DeleteProfile(profile);
// Update the profile, creating a new file
profile.Name = name;
AddOrUpdate(profile);
}
- public static void DeleteProfile(ProfileModel profile)
+ public static void DeleteProfile(ProfileModel prof)
{
+ // Remove from datastore
+ lock (Profiles)
+ {
+ // Get the profile from the datastore instead of just the provided value, to be certain it is removed
+ var dsProfile = Profiles.FirstOrDefault(p => p.GameName == prof.GameName &&
+ p.Name == prof.Name &&
+ p.KeyboardSlug == prof.KeyboardSlug);
+ if (dsProfile != null)
+ Profiles.Remove(dsProfile);
+ }
+
// Remove the file
- var path = ProfileFolder + $@"\{profile.KeyboardSlug}\{profile.GameName}\{profile.Name}.json";
+ var path = ProfileFolder + $@"\{prof.KeyboardSlug}\{prof.GameName}\{prof.Name}.json";
if (File.Exists(path))
File.Delete(path);
}
diff --git a/Artemis/Artemis/DeviceProviders/Corsair/CorsairKeyboards.cs b/Artemis/Artemis/DeviceProviders/Corsair/CorsairKeyboards.cs
index 3a64c1099..b739b0800 100644
--- a/Artemis/Artemis/DeviceProviders/Corsair/CorsairKeyboards.cs
+++ b/Artemis/Artemis/DeviceProviders/Corsair/CorsairKeyboards.cs
@@ -10,7 +10,6 @@ using CUE.NET;
using CUE.NET.Brushes;
using CUE.NET.Devices.Generic.Enums;
using CUE.NET.Devices.Keyboard;
-using CUE.NET.Devices.Keyboard.Enums;
using CUE.NET.Devices.Keyboard.Keys;
using Ninject.Extensions.Logging;
using Point = System.Drawing.Point;
@@ -78,6 +77,11 @@ namespace Artemis.DeviceProviders.Corsair
break;
}
+// Height = 7;
+// Width = 18;
+// Slug = "corsair-k65-rgb";
+// PreviewSettings = new PreviewSettings(610, 240, new Thickness(0, -30, 0, 0), Resources.k65);
+
Logger.Debug("Corsair SDK reported device as: {0}", _keyboard.DeviceInfo.Model);
_keyboard.Brush = _keyboardBrush ?? (_keyboardBrush = new ImageBrush());
}
@@ -121,7 +125,7 @@ namespace Artemis.DeviceProviders.Corsair
{
var widthMultiplier = Width/_keyboard.KeyboardRectangle.Width;
var heightMultiplier = Height/_keyboard.KeyboardRectangle.Height;
-
+
CorsairKey cueKey = null;
try
{
@@ -132,7 +136,7 @@ namespace Artemis.DeviceProviders.Corsair
{
// ignored
}
-
+
if (cueKey != null)
return new KeyMatch(keyCode, (int) (cueKey.KeyRectangle.X*widthMultiplier),
(int) (cueKey.KeyRectangle.Y*heightMultiplier));
diff --git a/Artemis/Artemis/DeviceProviders/Corsair/Utilities/KeyMap.cs b/Artemis/Artemis/DeviceProviders/Corsair/Utilities/KeyMap.cs
index aa8f34795..6c6232bd4 100644
--- a/Artemis/Artemis/DeviceProviders/Corsair/Utilities/KeyMap.cs
+++ b/Artemis/Artemis/DeviceProviders/Corsair/Utilities/KeyMap.cs
@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.Windows.Forms;
using CUE.NET.Devices.Keyboard.Enums;
-using CUE.NET.Devices.Keyboard.Keys;
namespace Artemis.DeviceProviders.Corsair.Utilities
{
diff --git a/Artemis/Artemis/DeviceProviders/Razer/BlackWidow.cs b/Artemis/Artemis/DeviceProviders/Razer/BlackWidow.cs
index 588640cf5..5aa6e9c1e 100644
--- a/Artemis/Artemis/DeviceProviders/Razer/BlackWidow.cs
+++ b/Artemis/Artemis/DeviceProviders/Razer/BlackWidow.cs
@@ -7,7 +7,6 @@ using Artemis.DeviceProviders.Razer.Utilities;
using Artemis.Properties;
using Corale.Colore.Core;
using Corale.Colore.Razer;
-using Corale.Colore.Razer.Keyboard;
using Constants = Corale.Colore.Razer.Keyboard.Constants;
namespace Artemis.DeviceProviders.Razer
@@ -29,9 +28,9 @@ namespace Artemis.DeviceProviders.Razer
public override bool CanEnable()
{
- if (!Chroma.IsSdkAvailable())
+ if (!Chroma.SdkAvailable)
return false;
-
+
// Some people have Synapse installed, but not a Chroma keyboard, deal with this
var blackWidowFound = Chroma.Instance.Query(Devices.Blackwidow).Connected;
var blackWidowTeFound = Chroma.Instance.Query(Devices.BlackwidowTe).Connected;
diff --git a/Artemis/Artemis/DeviceProviders/Razer/Utilities/RazerUtilities.cs b/Artemis/Artemis/DeviceProviders/Razer/Utilities/RazerUtilities.cs
index b8a380416..2ec0ebd43 100644
--- a/Artemis/Artemis/DeviceProviders/Razer/Utilities/RazerUtilities.cs
+++ b/Artemis/Artemis/DeviceProviders/Razer/Utilities/RazerUtilities.cs
@@ -1,6 +1,7 @@
using System.Drawing;
using Artemis.Utilities;
using Corale.Colore.Razer.Keyboard.Effects;
+using Color = Corale.Colore.Core.Color;
namespace Artemis.DeviceProviders.Razer.Utilities
{
@@ -13,8 +14,13 @@ namespace Artemis.DeviceProviders.Razer.Utilities
b = ImageUtilities.ResizeImage(b, width, height);
for (var y = 0; y < b.Height; y++)
+ {
for (var x = 0; x < b.Width; x++)
- keyboardGrid[y, x] = b.GetPixel(x, y);
+ {
+ var pixel = b.GetPixel(x, y);
+ keyboardGrid[y, x] = new Color(pixel.R, pixel.G, pixel.B);
+ }
+ }
return keyboardGrid;
}
diff --git a/Artemis/Artemis/InjectionModules/ArtemisModules.cs b/Artemis/Artemis/InjectionModules/ArtemisModules.cs
index 68f35bd1a..a8c38414c 100644
--- a/Artemis/Artemis/InjectionModules/ArtemisModules.cs
+++ b/Artemis/Artemis/InjectionModules/ArtemisModules.cs
@@ -10,6 +10,7 @@ using Artemis.Modules.Games.Dota2;
using Artemis.Modules.Games.Overwatch;
using Artemis.Modules.Games.RocketLeague;
using Artemis.Modules.Games.TheDivision;
+using Artemis.Modules.Games.UnrealTournament;
using Artemis.Modules.Games.Witcher3;
using Artemis.Modules.Overlays.VolumeDisplay;
using Artemis.Profiles.Layers.Animations;
@@ -46,6 +47,7 @@ namespace Artemis.InjectionModules
Bind().To().InSingletonScope();
Bind().To().InSingletonScope();
Bind().To().InSingletonScope();
+ Bind().To().InSingletonScope();
// Overlays
Bind().To().InSingletonScope();
diff --git a/Artemis/Artemis/Managers/LoopManager.cs b/Artemis/Artemis/Managers/LoopManager.cs
index a8f91935a..f5ba8c957 100644
--- a/Artemis/Artemis/Managers/LoopManager.cs
+++ b/Artemis/Artemis/Managers/LoopManager.cs
@@ -65,7 +65,7 @@ namespace Artemis.Managers
while (_deviceManager.ChangingKeyboard)
Thread.Sleep(200);
-
+
// If still null, no last keyboard, so stop.
if (_deviceManager.ActiveKeyboard == null)
{
diff --git a/Artemis/Artemis/Managers/MainManager.cs b/Artemis/Artemis/Managers/MainManager.cs
index bec1c129d..09d10be9d 100644
--- a/Artemis/Artemis/Managers/MainManager.cs
+++ b/Artemis/Artemis/Managers/MainManager.cs
@@ -1,13 +1,10 @@
using System;
-using System.Diagnostics;
using System.Linq;
using System.Timers;
using Artemis.Events;
using Artemis.Models;
-using Artemis.Modules.Effects.ProfilePreview;
using Artemis.Utilities.DataReaders;
using Artemis.Utilities.GameState;
-using Artemis.Utilities.Keyboard;
using Artemis.ViewModels;
using Caliburn.Micro;
using Ninject;
@@ -25,8 +22,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 +32,7 @@ namespace Artemis.Managers
DeviceManager = deviceManager;
EffectManager = effectManager;
ProfileManager = profileManager;
+ PipeServer = pipeServer;
_processTimer = new Timer(1000);
_processTimer.Elapsed += ScanProcesses;
@@ -48,7 +46,6 @@ namespace Artemis.Managers
GameStateWebServer.Start();
// Start the named pipe
- PipeServer = new PipeServer();
PipeServer.Start("artemis");
Logger.Info("Intialized MainManager");
diff --git a/Artemis/Artemis/Managers/ProfileManager.cs b/Artemis/Artemis/Managers/ProfileManager.cs
index 2c1861c66..50edc8d10 100644
--- a/Artemis/Artemis/Managers/ProfileManager.cs
+++ b/Artemis/Artemis/Managers/ProfileManager.cs
@@ -73,6 +73,7 @@ namespace Artemis.Managers
// LoopManager might be running, this method won't do any harm in that case.
_loopManager.StartAsync();
+ ProfilePreviewModel.ProfileViewModel = activePreview.ProfileEditor.ProfileViewModel;
if (!ReferenceEquals(ProfilePreviewModel.Profile, activePreview.ProfileEditor.SelectedProfile))
ProfilePreviewModel.Profile = activePreview.ProfileEditor.SelectedProfile;
}
diff --git a/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs b/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs
index 6566a68fe..513a9619d 100644
--- a/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs
+++ b/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs
@@ -7,6 +7,8 @@ using Artemis.Models;
using Artemis.Models.Interfaces;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
+using Artemis.ViewModels.Profiles;
+using Castle.Components.DictionaryAdapter;
namespace Artemis.Modules.Effects.ProfilePreview
{
@@ -17,6 +19,8 @@ namespace Artemis.Modules.Effects.ProfilePreview
Name = "Profile Preview";
}
+ public ProfileViewModel ProfileViewModel { get; set; }
+
public override void Dispose()
{
Initialized = false;
@@ -33,7 +37,7 @@ namespace Artemis.Modules.Effects.ProfilePreview
public override List GetRenderLayers(bool keyboardOnly)
{
- return Profile.GetRenderLayers(DataModel, keyboardOnly, true);
+ return ProfileViewModel != null ? ProfileViewModel.GetRenderLayers() : new EditableList();
}
public override void Render(RenderFrame frame, bool keyboardOnly)
diff --git a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeView.xaml b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeView.xaml
index e591ac8f9..0a8459b29 100644
--- a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeView.xaml
+++ b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeView.xaml
@@ -24,7 +24,7 @@
diff --git a/Artemis/Artemis/Modules/Games/Dota2/Dota2View.xaml b/Artemis/Artemis/Modules/Games/Dota2/Dota2View.xaml
index 6adaf23ee..336f2b1d7 100644
--- a/Artemis/Artemis/Modules/Games/Dota2/Dota2View.xaml
+++ b/Artemis/Artemis/Modules/Games/Dota2/Dota2View.xaml
@@ -24,7 +24,7 @@
diff --git a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs
index 618d90564..72c98e3cb 100644
--- a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs
+++ b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Threading;
using System.Windows.Media;
using Artemis.Events;
using Artemis.Managers;
@@ -98,9 +97,7 @@ namespace Artemis.Modules.Games.Overwatch
private void PipeServerOnPipeMessage(string message)
{
-
- _lastMessage = message;
-
+ _lastMessage = message;
}
public override void Update()
diff --git a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchView.xaml b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchView.xaml
index 1d5c7d9ad..309d225a7 100644
--- a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchView.xaml
+++ b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchView.xaml
@@ -17,13 +17,13 @@
-
+
@@ -35,6 +35,7 @@
+
diff --git a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueModel.cs b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueModel.cs
index 6895b0a34..3cc60a1b9 100644
--- a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueModel.cs
+++ b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueModel.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using Artemis.Managers;
using Artemis.Models;
diff --git a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueView.xaml b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueView.xaml
index 657690ccd..d59f8c89b 100644
--- a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueView.xaml
+++ b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueView.xaml
@@ -28,7 +28,7 @@
diff --git a/Artemis/Artemis/Modules/Games/UnrealTournament/Resources/redeemer.gif b/Artemis/Artemis/Modules/Games/UnrealTournament/Resources/redeemer.gif
new file mode 100644
index 000000000..8b5947845
Binary files /dev/null and b/Artemis/Artemis/Modules/Games/UnrealTournament/Resources/redeemer.gif differ
diff --git a/Artemis/Artemis/Modules/Games/UnrealTournament/Resources/ut-plugin.zip b/Artemis/Artemis/Modules/Games/UnrealTournament/Resources/ut-plugin.zip
new file mode 100644
index 000000000..c013a0f6f
Binary files /dev/null and b/Artemis/Artemis/Modules/Games/UnrealTournament/Resources/ut-plugin.zip differ
diff --git a/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournament.Designer.cs b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournament.Designer.cs
new file mode 100644
index 000000000..1458db06a
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournament.Designer.cs
@@ -0,0 +1,62 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Artemis.Modules.Games.UnrealTournament {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
+ internal sealed partial class UnrealTournament : global::System.Configuration.ApplicationSettingsBase {
+
+ private static UnrealTournament defaultInstance = ((UnrealTournament)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new UnrealTournament())));
+
+ public static UnrealTournament Default {
+ get {
+ return defaultInstance;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool Enabled {
+ get {
+ return ((bool)(this["Enabled"]));
+ }
+ set {
+ this["Enabled"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("Default")]
+ public string LastProfile {
+ get {
+ return ((string)(this["LastProfile"]));
+ }
+ set {
+ this["LastProfile"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("")]
+ public string GameDirectory {
+ get {
+ return ((string)(this["GameDirectory"]));
+ }
+ set {
+ this["GameDirectory"] = value;
+ }
+ }
+ }
+}
diff --git a/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournament.settings b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournament.settings
new file mode 100644
index 000000000..8052f2dea
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournament.settings
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ True
+
+
+ Default
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentDataModel.cs b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentDataModel.cs
new file mode 100644
index 000000000..aa2deb1b9
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentDataModel.cs
@@ -0,0 +1,104 @@
+using Artemis.Models.Interfaces;
+using Newtonsoft.Json;
+
+namespace Artemis.Modules.Games.UnrealTournament
+{
+ public class UnrealTournamentDataModel : IDataModel
+ {
+ public State State { get; set; }
+ public Environment Environment { get; set; }
+ public Player Player { get; set; }
+ }
+
+ public enum State
+ {
+ MainMenu,
+ Spectating,
+ Alive,
+ Dead
+ }
+
+ public class Player
+ {
+ public int Health { get; set; }
+ public int Armor { get; set; }
+ public PlayerState State { get; set; }
+ public Inventory Inventory { get; set; }
+ public Weapon Weapon { get; set; }
+ }
+
+ public class PlayerState
+ {
+ public string PlayerName { get; set; }
+ public string UniqueId { get; set; }
+ public int Score { get; set; }
+ [JsonProperty("Team Num")]
+ public int TeamNum { get; set; }
+ public int RankCheck { get; set; }
+ [JsonProperty("Duel Rank")]
+ public int DuelRank { get; set; }
+ public int No_of_Duel_Played { get; set; }
+ [JsonProperty("CTF Rank")]
+ public int CTFRank { get; set; }
+ public int No_CTF_MatchesPlayed { get; set; }
+ [JsonProperty("TDM Rank")]
+ public int TDMRank { get; set; }
+ public int No_TDM_MatchesPlayed { get; set; }
+ public int DMRank { get; set; }
+ public int No_DM_Matches_Played { get; set; }
+ public int ShowdownRank { get; set; }
+ public int No_Showdowns { get; set; }
+ }
+
+ public class Inventory
+ {
+ public bool HasJumpBoots { get; set; }
+ public bool HasInvisibility { get; set; }
+ public bool HasBerserk { get; set; }
+ public bool HasUDamage { get; set; }
+ public bool HasThighPads { get; set; }
+ public bool HasShieldBelt { get; set; }
+ public bool HasChestArmor { get; set; }
+ public bool HasHelmet { get; set; }
+ }
+
+ public class Weapon
+ {
+ public string Name { get; set; }
+ public int Ammo { get; set; }
+ public int MaxAmmo { get; set; }
+ public bool IsFiring { get; set; }
+ public int FireMode { get; set; }
+ public ZoomState ZoomState { get; set; }
+ }
+
+ public enum ZoomState
+ {
+ Unzoomed = 0,
+ Zoomed = 3,
+ ZoomingIn = 1,
+ ZoomingOut = 2
+ }
+
+ public class Environment
+ {
+ public string GameMode { get; set; }
+ public bool MatchStarted { get; set; }
+ public int GoalScore { get; set; }
+ public string ServerName { get; set; }
+ public bool bWeaponStay { get; set; }
+ public bool bTeamGame { get; set; }
+ public bool bAllowTeamSwitches { get; set; }
+ public bool bStopGameClock { get; set; }
+ public bool bCasterControl { get; set; }
+ public bool bForcedBalance { get; set; }
+ public bool bPlayPlayerIntro { get; set; }
+ public int TimeLimit { get; set; }
+ public int SpawnProtectionTime { get; set; }
+ public int RemainingTime { get; set; }
+ public int ElapsedTime { get; set; }
+ public int RespawnWaitTime { get; set; }
+ public int ForceRespawnTime { get; set; }
+ }
+
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentModel.cs b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentModel.cs
new file mode 100644
index 000000000..a1863c2f9
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentModel.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using Artemis.Managers;
+using Artemis.Models;
+using Artemis.Profiles.Layers.Models;
+using Newtonsoft.Json;
+
+namespace Artemis.Modules.Games.UnrealTournament
+{
+ public class UnrealTournamentModel : GameModel
+ {
+ public UnrealTournamentModel(MainManager mainManager, UnrealTournamentSettings settings)
+ : base(mainManager, settings, new UnrealTournamentDataModel())
+ {
+ Name = "UnrealTournament";
+ ProcessName = "UE4-Win64-Shipping";
+ Scale = 4;
+ Enabled = Settings.Enabled;
+ Initialized = false;
+ }
+
+ public int Scale { get; set; }
+
+ public override void Dispose()
+ {
+ Initialized = false;
+ MainManager.PipeServer.PipeMessage -= PipeServerOnPipeMessage;
+ }
+
+ public override void Enable()
+ {
+ MainManager.PipeServer.PipeMessage += PipeServerOnPipeMessage;
+ Initialized = true;
+ }
+
+ private void PipeServerOnPipeMessage(string message)
+ {
+ if (!message.Contains("\"Environment\":"))
+ return;
+
+ // Parse the JSON
+ try
+ {
+ DataModel = JsonConvert.DeserializeObject(message);
+ }
+ catch (Exception)
+ {
+ //ignored
+ }
+ }
+
+ public override void Update()
+ {
+ }
+
+ public override List GetRenderLayers(bool keyboardOnly)
+ {
+ return Profile.GetRenderLayers(DataModel, keyboardOnly);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentSettings.cs b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentSettings.cs
new file mode 100644
index 000000000..9b27c884a
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentSettings.cs
@@ -0,0 +1,36 @@
+using Artemis.Models;
+
+namespace Artemis.Modules.Games.UnrealTournament
+{
+ public class UnrealTournamentSettings : GameSettings
+ {
+ public UnrealTournamentSettings()
+ {
+ 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();
+ }
+
+ public sealed override void ToDefault()
+ {
+ Enabled = true;
+ GameDirectory = string.Empty;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentView.xaml b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentView.xaml
new file mode 100644
index 000000000..df2b3afc9
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentView.xaml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentView.xaml.cs b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentView.xaml.cs
new file mode 100644
index 000000000..e23603ded
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentView.xaml.cs
@@ -0,0 +1,15 @@
+using System.Windows.Controls;
+
+namespace Artemis.Modules.Games.UnrealTournament
+{
+ ///
+ /// Interaction logic for UnrealTournamentView.xaml
+ ///
+ public partial class UnrealTournamentView : UserControl
+ {
+ public UnrealTournamentView()
+ {
+ InitializeComponent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentViewModel.cs b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentViewModel.cs
new file mode 100644
index 000000000..fc19fc0fe
--- /dev/null
+++ b/Artemis/Artemis/Modules/Games/UnrealTournament/UnrealTournamentViewModel.cs
@@ -0,0 +1,126 @@
+using System;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using System.Reflection;
+using System.Windows.Forms;
+using Artemis.DAL;
+using Artemis.InjectionFactories;
+using Artemis.Managers;
+using Artemis.Properties;
+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
+ {
+ 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);
+ FindGame();
+ InstallGif();
+ }
+
+ 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(
+ File.ReadAllText(@"C:\ProgramData\Epic\UnrealEngineLauncher\LauncherInstalled.dat"));
+ var utEntry =
+ json["InstallationList"].Children()
+ .FirstOrDefault(c => c["AppName"].Value() == "UnrealTournamentDev");
+ if (utEntry == null)
+ return;
+
+ var utDir = utEntry["InstallLocation"].Value();
+ // 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);
+ }
+
+ private void InstallGif()
+ {
+ var gif = Resources.redeemer;
+ ProfileProvider.InsertGif(ProfileProvider.GetAll()
+ .Where(p => p.GameName == "UnrealTournament" && p.Name == "Default"), "Redeemer GIF", gif, "redeemer");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/Resources/Witcher3/Witcher3Artemis.zip b/Artemis/Artemis/Modules/Games/Witcher3/Resources/witcher3-mod.zip
similarity index 100%
rename from Artemis/Artemis/Resources/Witcher3/Witcher3Artemis.zip
rename to Artemis/Artemis/Modules/Games/Witcher3/Resources/witcher3-mod.zip
diff --git a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3View.xaml b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3View.xaml
index 66d62178d..c8e7be806 100644
--- a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3View.xaml
+++ b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3View.xaml
@@ -23,7 +23,7 @@
diff --git a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs
index 0b6ba18fd..f57b297d8 100644
--- a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs
+++ b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs
@@ -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);
@@ -80,7 +80,8 @@ namespace Artemis.Modules.Games.Witcher3
archive.ExtractToDirectory(folder + @"witcher3-mod", true);
- System.Diagnostics.Process.Start(new ProcessStartInfo("https://github.com/SpoinkyNL/Artemis/wiki/The-Witcher-3"));
+ System.Diagnostics.Process.Start(
+ new ProcessStartInfo("https://github.com/SpoinkyNL/Artemis/wiki/The-Witcher-3"));
return;
}
}
diff --git a/Artemis/Artemis/Modules/Games/WorldofWarcraft/WoW.settings b/Artemis/Artemis/Modules/Games/WorldofWarcraft/WoW.settings
index c2d66228b..db9c19f89 100644
--- a/Artemis/Artemis/Modules/Games/WorldofWarcraft/WoW.settings
+++ b/Artemis/Artemis/Modules/Games/WorldofWarcraft/WoW.settings
@@ -1,5 +1,7 @@
-
+
+
diff --git a/Artemis/Artemis/Modules/Games/WorldofWarcraft/WoWAddresses.cs b/Artemis/Artemis/Modules/Games/WorldofWarcraft/WoWAddresses.cs
index 5d600759d..3abc6f8fc 100644
--- a/Artemis/Artemis/Modules/Games/WorldofWarcraft/WoWAddresses.cs
+++ b/Artemis/Artemis/Modules/Games/WorldofWarcraft/WoWAddresses.cs
@@ -142,12 +142,6 @@ namespace Artemis.Modules.Games.WorldofWarcraft
objectTYPE = 0x10
}
- public class ObjectManagerClass
- {
- public static uint clientConnection;
- public static uint sCurMgr;
- }
-
public enum Party
{
NumOfPlayers = 200,
@@ -252,5 +246,11 @@ namespace Artemis.Modules.Games.WorldofWarcraft
{
CGUnit_C__GetFacing = 0x35
}
+
+ public class ObjectManagerClass
+ {
+ public static uint clientConnection;
+ public static uint sCurMgr;
+ }
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Modules/Games/WorldofWarcraft/WoWModel.cs b/Artemis/Artemis/Modules/Games/WorldofWarcraft/WoWModel.cs
index 093e6bd43..c045f8763 100644
--- a/Artemis/Artemis/Modules/Games/WorldofWarcraft/WoWModel.cs
+++ b/Artemis/Artemis/Modules/Games/WorldofWarcraft/WoWModel.cs
@@ -2,7 +2,6 @@
using Artemis.Managers;
using Artemis.Models;
using Artemis.Profiles.Layers.Models;
-using Artemis.Utilities;
using Artemis.Utilities.Memory;
namespace Artemis.Modules.Games.WorldofWarcraft
@@ -51,7 +50,5 @@ namespace Artemis.Modules.Games.WorldofWarcraft
{
return Profile.GetRenderLayers(DataModel, keyboardOnly);
}
-
-
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/NLog.xsd b/Artemis/Artemis/NLog.xsd
index dc821bc0d..c489255c0 100644
--- a/Artemis/Artemis/NLog.xsd
+++ b/Artemis/Artemis/NLog.xsd
@@ -232,7 +232,6 @@
-
@@ -1020,8 +1019,8 @@
-
+
@@ -1093,16 +1092,16 @@
Size in bytes above which log files will be automatically archived. Warning: combining this with isn't supported. We cannot create multiple archive files, if they should have the same name. Choose:
-
-
- Maximum number of archive files that should be kept.
-
-
Indicates whether to compress archive files into the zip archive format.
+
+
+ Maximum number of archive files that should be kept.
+
+
Gets or set a value indicating whether a managed file stream is forced, instead of used the native implementation.
@@ -2238,6 +2237,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2334,8 +2345,14 @@
+
+
+
+ Option to render the empty object value {}
+
+
Option to suppress the extra spaces in the output json
diff --git a/Artemis/Artemis/Profiles/Layers/Animations/GrowAnimation.cs b/Artemis/Artemis/Profiles/Layers/Animations/GrowAnimation.cs
index da70c3808..ab8d9279c 100644
--- a/Artemis/Artemis/Profiles/Layers/Animations/GrowAnimation.cs
+++ b/Artemis/Artemis/Profiles/Layers/Animations/GrowAnimation.cs
@@ -1,4 +1,5 @@
-using System.Windows;
+using System;
+using System.Windows;
using System.Windows.Media;
using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models;
@@ -7,10 +8,16 @@ namespace Artemis.Profiles.Layers.Animations
{
public class GrowAnimation : ILayerAnimation
{
+ private DateTime _lastUpdate;
public string Name { get; } = "Grow";
public void Update(LayerModel layerModel, bool updateAnimations)
{
+ // Reset animation progress if layer wasn't drawn for 100ms
+ if (new TimeSpan(0, 0, 0, 0, 100) < DateTime.Now - _lastUpdate)
+ layerModel.Properties.AnimationProgress = 0;
+ _lastUpdate = DateTime.Now;
+
var progress = layerModel.Properties.AnimationProgress;
if (MustExpire(layerModel))
@@ -24,7 +31,7 @@ namespace Artemis.Profiles.Layers.Animations
public void Draw(LayerPropertiesModel props, LayerPropertiesModel applied, DrawingContext c)
{
- if (applied.Brush == null)
+ if (applied?.Brush == null)
return;
const int scale = 4;
diff --git a/Artemis/Artemis/Profiles/Layers/Animations/PulseAnimation.cs b/Artemis/Artemis/Profiles/Layers/Animations/PulseAnimation.cs
index 0d5e34253..28a8f83aa 100644
--- a/Artemis/Artemis/Profiles/Layers/Animations/PulseAnimation.cs
+++ b/Artemis/Artemis/Profiles/Layers/Animations/PulseAnimation.cs
@@ -8,11 +8,18 @@ namespace Artemis.Profiles.Layers.Animations
{
public class PulseAnimation : ILayerAnimation
{
+ private DateTime _lastUpdate;
public string Name { get; } = "Pulse";
public void Update(LayerModel layerModel, bool updateAnimations)
{
+ // Reset animation progress if layer wasn't drawn for 100ms
+ if (new TimeSpan(0, 0, 0, 0, 100) < DateTime.Now - _lastUpdate)
+ layerModel.Properties.AnimationProgress = 0;
+ _lastUpdate = DateTime.Now;
+
var progress = layerModel.Properties.AnimationProgress;
+
if (MustExpire(layerModel))
progress = 0;
progress = progress + layerModel.Properties.AnimationSpeed/2;
diff --git a/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerAnimation.cs b/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerAnimation.cs
index 1b311956b..e5554a8d3 100644
--- a/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerAnimation.cs
+++ b/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerAnimation.cs
@@ -8,6 +8,7 @@ namespace Artemis.Profiles.Layers.Interfaces
{
[JsonIgnore]
string Name { get; }
+
void Update(LayerModel layerModel, bool updateAnimations);
void Draw(LayerPropertiesModel props, LayerPropertiesModel applied, DrawingContext c);
bool MustExpire(LayerModel layer);
diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs
index 3e93af114..0f04dfddf 100644
--- a/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs
+++ b/Artemis/Artemis/Profiles/Layers/Models/LayerConditionModel.cs
@@ -31,7 +31,7 @@ namespace Artemis.Profiles.Layers.Models
// Put the subject in a list, allowing Dynamic Linq to be used.
if (Type == "String")
{
- return _interpreter.Eval($"subject.{Field}.ToLower() {Operator} value",
+ return _interpreter.Eval($"subject.{Field}.ToLower(){Operator}(value)",
new Parameter("subject", subject.GetType(), subject),
new Parameter("value", Value.ToLower()));
}
diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs
index c026b17c9..5b8a58cfb 100644
--- a/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs
+++ b/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs
@@ -123,7 +123,7 @@ namespace Artemis.Profiles.Layers.Models
public IEnumerable GetLayers()
{
var layers = new List();
- foreach (var layerModel in Children)
+ foreach (var layerModel in Children.OrderBy(c => c.Order))
{
layers.Add(layerModel);
layers.AddRange(layerModel.GetLayers());
diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs
index fa6aee5a5..a6eb1ea34 100644
--- a/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs
+++ b/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs
@@ -68,7 +68,7 @@ namespace Artemis.Profiles.Layers.Models
public Rect GetRect(int scale = 4)
{
- return new Rect(X * scale, Y * scale, Width * scale, Height * scale);
+ return new Rect(X*scale, Y*scale, Width*scale, Height*scale);
}
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioPropertiesView.xaml b/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioPropertiesView.xaml
index 2fed86b24..4d6484b53 100644
--- a/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioPropertiesView.xaml
+++ b/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioPropertiesView.xaml
@@ -44,7 +44,8 @@
VerticalAlignment="Top" Height="18" Width="130" />
-
+
diff --git a/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs b/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs
index a66778ac4..7fd087c40 100644
--- a/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs
+++ b/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs
@@ -20,18 +20,15 @@ namespace Artemis.Profiles.Layers.Types.Audio
{
internal class AudioType : ILayerType
{
+ private readonly List _audioLayers = new List();
private readonly MMDevice _device;
- private readonly MainManager _mainManager;
private readonly SampleAggregator _sampleAggregator = new SampleAggregator(2048);
private readonly WasapiLoopbackCapture _waveIn;
- private readonly List _audioLayers = new List();
private int _lines;
- private AudioPropertiesModel _properties;
private AudioPropertiesModel _previousSettings;
public AudioType(MainManager mainManager)
{
- _mainManager = mainManager;
_device =
new MMDeviceEnumerator().EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active).FirstOrDefault();
@@ -107,6 +104,26 @@ namespace Artemis.Profiles.Layers.Types.Audio
}
}
+ public void SetupProperties(LayerModel layerModel)
+ {
+ if (layerModel.Properties is AudioPropertiesModel)
+ return;
+
+ layerModel.Properties = new AudioPropertiesModel(layerModel.Properties)
+ {
+ FadeSpeed = 0.2,
+ Sensitivity = 2
+ };
+ }
+
+ public LayerPropertiesViewModel SetupViewModel(LayerPropertiesViewModel layerPropertiesViewModel,
+ List layerAnimations, IDataModel dataModel, LayerModel proposedLayer)
+ {
+ if (layerPropertiesViewModel is AudioPropertiesViewModel)
+ return layerPropertiesViewModel;
+ return new AudioPropertiesViewModel(proposedLayer, dataModel);
+ }
+
private void CompareSettings(LayerModel layerModel)
{
var settings = (AudioPropertiesModel) layerModel.Properties;
@@ -133,26 +150,6 @@ namespace Artemis.Profiles.Layers.Types.Audio
}
}
- public void SetupProperties(LayerModel layerModel)
- {
- if (layerModel.Properties is AudioPropertiesModel)
- return;
-
- layerModel.Properties = new AudioPropertiesModel(layerModel.Properties)
- {
- FadeSpeed = 0.2,
- Sensitivity = 2
- };
- }
-
- public LayerPropertiesViewModel SetupViewModel(LayerPropertiesViewModel layerPropertiesViewModel,
- List layerAnimations, IDataModel dataModel, LayerModel proposedLayer)
- {
- if (layerPropertiesViewModel is AudioPropertiesViewModel)
- return layerPropertiesViewModel;
- return new AudioPropertiesViewModel(proposedLayer, dataModel);
- }
-
private void FftCalculated(object sender, FftEventArgs e)
{
lock (SpectrumData)
diff --git a/Artemis/Artemis/Profiles/Layers/Types/KeyPress/KeyPressPropertiesView.xaml b/Artemis/Artemis/Profiles/Layers/Types/KeyPress/KeyPressPropertiesView.xaml
index 68b8d3787..ef1366a7e 100644
--- a/Artemis/Artemis/Profiles/Layers/Types/KeyPress/KeyPressPropertiesView.xaml
+++ b/Artemis/Artemis/Profiles/Layers/Types/KeyPress/KeyPressPropertiesView.xaml
@@ -44,7 +44,8 @@
VerticalAlignment="Top" Height="18" Width="130" />
-
+
diff --git a/Artemis/Artemis/Profiles/ProfileModel.cs b/Artemis/Artemis/Profiles/ProfileModel.cs
index 2e96a518f..3208d3a59 100644
--- a/Artemis/Artemis/Profiles/ProfileModel.cs
+++ b/Artemis/Artemis/Profiles/ProfileModel.cs
@@ -63,7 +63,7 @@ namespace Artemis.Profiles
// Remove the clip
c.Pop();
}
-
+
using (var bmp = ImageUtilities.DrawingVisualToBitmap(visual, keyboardRect))
keyboard.DrawImage(bmp, new PointF(0, 0));
}
@@ -74,7 +74,7 @@ namespace Artemis.Profiles
public List GetLayers()
{
var layers = new List();
- foreach (var layerModel in Layers)
+ foreach (var layerModel in Layers.OrderBy(l => l.Order))
{
layers.Add(layerModel);
layers.AddRange(layerModel.GetLayers());
@@ -177,7 +177,7 @@ namespace Artemis.Profiles
{
foreach (var layer in GetLayers())
{
- if (!layer.LayerType.ShowInEdtor ||
+ if (!layer.LayerType.ShowInEdtor ||
!(Math.Abs(layer.Properties.Width - Width) < 0.01) ||
!(Math.Abs(layer.Properties.Height - Height) < 0.01))
continue;
diff --git a/Artemis/Artemis/Properties/Resources.Designer.cs b/Artemis/Artemis/Properties/Resources.Designer.cs
index a531595d2..99580a00c 100644
--- a/Artemis/Artemis/Properties/Resources.Designer.cs
+++ b/Artemis/Artemis/Properties/Resources.Designer.cs
@@ -288,6 +288,16 @@ namespace Artemis.Properties {
}
}
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap redeemer {
+ get {
+ object obj = ResourceManager.GetObject("redeemer", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Looks up a localized resource of type System.Byte[].
///
@@ -311,9 +321,19 @@ namespace Artemis.Properties {
///
/// Looks up a localized resource of type System.Byte[].
///
- 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));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Byte[].
+ ///
+ internal static byte[] witcher3_mod {
+ get {
+ object obj = ResourceManager.GetObject("witcher3_mod", resourceCulture);
return ((byte[])(obj));
}
}
diff --git a/Artemis/Artemis/Properties/Resources.resx b/Artemis/Artemis/Properties/Resources.resx
index efe0589cc..4d198f614 100644
--- a/Artemis/Artemis/Properties/Resources.resx
+++ b/Artemis/Artemis/Properties/Resources.resx
@@ -178,13 +178,19 @@
..\Resources\Keyboards\demo-gif.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
- ..\Resources\Witcher3\Witcher3Artemis.zip;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
..\Resources\Keyboards\g810.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
..\Resources\generic.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+ ..\Modules\Games\UnrealTournament\Resources\ut-plugin.zip;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Modules\Games\Witcher3\Resources\witcher3-mod.zip;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Modules\Games\UnrealTournament\Resources\redeemer.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
\ No newline at end of file
diff --git a/Artemis/Artemis/Resources/Keyboards/default-profiles.zip b/Artemis/Artemis/Resources/Keyboards/default-profiles.zip
index fc967a61f..dba026291 100644
Binary files a/Artemis/Artemis/Resources/Keyboards/default-profiles.zip and b/Artemis/Artemis/Resources/Keyboards/default-profiles.zip differ
diff --git a/Artemis/Artemis/Utilities/ColorHelpers.cs b/Artemis/Artemis/Utilities/ColorHelpers.cs
index a4d21dc72..a6adeaf35 100644
--- a/Artemis/Artemis/Utilities/ColorHelpers.cs
+++ b/Artemis/Artemis/Utilities/ColorHelpers.cs
@@ -118,7 +118,7 @@ namespace Artemis.Utilities
if (brush is RadialGradientBrush)
{
- var randomBrush = (RadialGradientBrush)brush.CloneCurrentValue();
+ var randomBrush = (RadialGradientBrush) brush.CloneCurrentValue();
var rand = GetRandomRainbowMediaColor();
foreach (var stop in randomBrush.GradientStops)
stop.Color = System.Windows.Media.Color.FromArgb(stop.Color.A, rand.R, rand.G, rand.B);
diff --git a/Artemis/Artemis/Utilities/Converters/NinjectCustomConverter.cs b/Artemis/Artemis/Utilities/Converters/NinjectCustomConverter.cs
index 1021a99c7..cf9135765 100644
--- a/Artemis/Artemis/Utilities/Converters/NinjectCustomConverter.cs
+++ b/Artemis/Artemis/Utilities/Converters/NinjectCustomConverter.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
using Newtonsoft.Json.Serialization;
using Ninject;
diff --git a/Artemis/Artemis/Utilities/DataReaders/DllManager.cs b/Artemis/Artemis/Utilities/DataReaders/DllManager.cs
index 6f82a3b77..bc64062a4 100644
--- a/Artemis/Artemis/Utilities/DataReaders/DllManager.cs
+++ b/Artemis/Artemis/Utilities/DataReaders/DllManager.cs
@@ -1,6 +1,5 @@
using System;
using System.IO;
-using Artemis.Modules.Games.Overwatch;
using Artemis.Properties;
using Microsoft.Win32;
using NLog;
@@ -11,6 +10,23 @@ namespace Artemis.Utilities.DataReaders
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
+ #region Razer
+
+ public static void PlaceRazerDll(string path)
+ {
+ try
+ {
+ File.WriteAllBytes(path + @"\RzChromaSDK64.dll", Resources.RzChromaSDK64);
+ Logger.Debug("Successfully placed Razer DLL in {0}", path);
+ }
+ catch (Exception e)
+ {
+ Logger.Error(e, "Couldn't place Razer DLL in {0}", path);
+ }
+ }
+
+ #endregion
+
#region Logitech
private const string LogitechPath = @"C:\Program Files\Logitech Gaming Software\SDK\LED\x64\";
@@ -95,22 +111,5 @@ namespace Artemis.Utilities.DataReaders
}
#endregion
-
- #region Razer
-
- public static void PlaceRazerDll(string path)
- {
- try
- {
- File.WriteAllBytes(path + @"\RzChromaSDK64.dll", Resources.RzChromaSDK64);
- Logger.Debug("Successfully placed Razer DLL in {0}", path);
- }
- catch (Exception e)
- {
- Logger.Error(e, "Couldn't place Razer DLL in {0}", path);
- }
- }
-
- #endregion
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Utilities/DataReaders/PipeServer.cs b/Artemis/Artemis/Utilities/DataReaders/PipeServer.cs
index 6cd907c3d..5430c7de9 100644
--- a/Artemis/Artemis/Utilities/DataReaders/PipeServer.cs
+++ b/Artemis/Artemis/Utilities/DataReaders/PipeServer.cs
@@ -1,10 +1,9 @@
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 +12,35 @@ namespace Artemis.Utilities.DataReaders
public class PipeServer
{
+ private readonly ILogger _logger;
private string _pipeName;
+ private NamedPipeServerStream _pipeServer;
+
+ public PipeServer(ILogger logger)
+ {
+ _logger = logger;
+ }
- public bool Running { get; set; }
public event DelegateMessage PipeMessage;
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);
+ pipeServer.Read(buffer, 0, 4096);
// 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);
+ }
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Utilities/ExtensionMethods.cs b/Artemis/Artemis/Utilities/ExtensionMethods.cs
index 0a4fe9fa1..cf626ed0f 100644
--- a/Artemis/Artemis/Utilities/ExtensionMethods.cs
+++ b/Artemis/Artemis/Utilities/ExtensionMethods.cs
@@ -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);
}
}
diff --git a/Artemis/Artemis/Utilities/GeneralHelpers.cs b/Artemis/Artemis/Utilities/GeneralHelpers.cs
index af9771b92..7898a4937 100644
--- a/Artemis/Artemis/Utilities/GeneralHelpers.cs
+++ b/Artemis/Artemis/Utilities/GeneralHelpers.cs
@@ -50,13 +50,15 @@ namespace Artemis.Utilities
if (ReferenceEquals(source, null))
return default(T);
- return (T)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(source), source.GetType());
+ return (T) JsonConvert.DeserializeObject(JsonConvert.SerializeObject(source), source.GetType());
}
public static object GetPropertyValue(object o, string path)
{
var propertyNames = path.Split('.');
var prop = o.GetType().GetProperty(propertyNames[0]);
+ if (prop == null)
+ return null;
var value = prop.GetValue(o, null);
if (propertyNames.Length == 1 || value == null)
diff --git a/Artemis/Artemis/Utilities/Memory/MemoryHelpers.cs b/Artemis/Artemis/Utilities/Memory/MemoryHelpers.cs
index 94a0d9493..7987498d9 100644
--- a/Artemis/Artemis/Utilities/Memory/MemoryHelpers.cs
+++ b/Artemis/Artemis/Utilities/Memory/MemoryHelpers.cs
@@ -38,7 +38,8 @@ namespace Artemis.Utilities.Memory
return address;
}
- public static T ReadMultilevelPointer(this IMemory memory, IntPtr address, params int[] offsets) where T : struct
+ public static T ReadMultilevelPointer(this IMemory memory, IntPtr address, params int[] offsets)
+ where T : struct
{
for (var i = 0; i < offsets.Length - 1; i++)
{
diff --git a/Artemis/Artemis/Utilities/Updater.cs b/Artemis/Artemis/Utilities/Updater.cs
index 6bd7c6ed9..adb673416 100644
--- a/Artemis/Artemis/Utilities/Updater.cs
+++ b/Artemis/Artemis/Utilities/Updater.cs
@@ -15,12 +15,12 @@ namespace Artemis.Utilities
{
public static class Updater
{
- public static int CurrentVersion = 1220;
+ public static int CurrentVersion = 1230;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public static async Task CheckForUpdate(MetroDialogService dialogService)
{
- Logger.Info("Checking for updates - Current version: 1.2.2.0");
+ Logger.Info("Checking for updates - Current version: 1.2.3.0");
if (!General.Default.CheckForUpdates)
return null;
diff --git a/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs
index 81f1b05ec..4f6bde1bc 100644
--- a/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs
+++ b/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs
@@ -31,6 +31,15 @@ namespace Artemis.ViewModels.Profiles
new NamedOperator("Not equal to", "!=")
};
+ private readonly NamedOperator[] _stringOperators =
+ {
+ new NamedOperator("Equal to", "=="),
+ new NamedOperator("Not equal to", "!="),
+ new NamedOperator("Contains", ".Contains"),
+ new NamedOperator("Starts with", ".StartsWith"),
+ new NamedOperator("Ends with", ".EndsWith")
+ };
+
private bool _enumValueIsVisible;
private bool _preselecting;
private GeneralHelpers.PropertyCollection _selectedDataModelProp;
@@ -156,6 +165,10 @@ namespace Artemis.ViewModels.Profiles
Enums.Add("False");
EnumValueIsVisible = true;
break;
+ case "String":
+ Operators.AddRange(_stringOperators);
+ UserValueIsVisible = true;
+ break;
default:
Operators.AddRange(_operators);
UserValueIsVisible = true;
diff --git a/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs
index 34a272f6e..94f599d50 100644
--- a/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs
+++ b/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs
@@ -422,6 +422,8 @@ namespace Artemis.ViewModels.Profiles
{
// Update the UI
Layers.Clear();
+ ProfileViewModel.SelectedLayer = null;
+
if (SelectedProfile != null)
Layers.AddRange(SelectedProfile.Layers);
@@ -431,7 +433,7 @@ namespace Artemis.ViewModels.Profiles
// A small delay to allow the profile list to rebuild
Task.Factory.StartNew(() =>
{
- Thread.Sleep(20);
+ Thread.Sleep(100);
ProfileViewModel.SelectedLayer = selectModel;
});
}
@@ -516,38 +518,30 @@ namespace Artemis.ViewModels.Profiles
{
if (SelectedProfile == null)
return;
-
- var oldName = SelectedProfile.Name;
- SelectedProfile.Name = await DialogService
- .ShowInputDialog("Rename profile", "Please enter a unique new profile name");
+
+ var name = await DialogService.ShowInputDialog("Rename profile", "Please enter a unique new profile name");
// Null when the user cancelled
- if (string.IsNullOrEmpty(SelectedProfile.Name) || SelectedProfile.Name.Length < 2)
- {
- SelectedProfile.Name = oldName;
+ if (string.IsNullOrEmpty(name) || name.Length < 2)
return;
- }
// Verify the name
- while (ProfileProvider.GetAll().Contains(SelectedProfile))
+ while (ProfileProvider.GetAll().Any(p => p.Name == name && p.GameName == SelectedProfile.GameName &&
+ p.KeyboardSlug == SelectedProfile.KeyboardSlug))
{
- SelectedProfile.Name = await DialogService.
- ShowInputDialog("Name already in use", "Please enter a unique new profile name");
+ name = await DialogService.ShowInputDialog("Name already in use", "Please enter a unique new profile name");
// Null when the user cancelled
- if (string.IsNullOrEmpty(SelectedProfile.Name) || SelectedProfile.Name.Length < 2)
- {
- SelectedProfile.Name = oldName;
+ if (string.IsNullOrEmpty(name) || name.Length < 2)
return;
- }
}
- var newName = SelectedProfile.Name;
- SelectedProfile.Name = oldName;
- ProfileProvider.RenameProfile(SelectedProfile, newName);
-
+ var profile = SelectedProfile;
+ SelectedProfile = null;
+ ProfileProvider.RenameProfile(profile, name);
+
+ LastProfile = name;
LoadProfiles();
- SelectedProfile = Profiles.FirstOrDefault(p => p.Name == newName);
}
public async void DuplicateProfile()
diff --git a/Artemis/Artemis/ViewModels/Profiles/ProfileViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/ProfileViewModel.cs
index aa567639c..a96f755a9 100644
--- a/Artemis/Artemis/ViewModels/Profiles/ProfileViewModel.cs
+++ b/Artemis/Artemis/ViewModels/Profiles/ProfileViewModel.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Timers;
using System.Windows;
@@ -10,10 +11,11 @@ using Artemis.Managers;
using Artemis.Modules.Effects.ProfilePreview;
using Artemis.Profiles;
using Artemis.Profiles.Layers.Models;
-using Artemis.Profiles.Layers.Types.Keyboard;
+using Artemis.Profiles.Layers.Types.Folder;
using Artemis.Properties;
using Artemis.Utilities;
using Caliburn.Micro;
+using Castle.Components.DictionaryAdapter;
using MahApps.Metro;
namespace Artemis.ViewModels.Profiles
@@ -30,6 +32,7 @@ namespace Artemis.ViewModels.Profiles
private Cursor _keyboardPreviewCursor;
private bool _resizing;
private LayerModel _selectedLayer;
+ private bool _showAll;
public ProfileViewModel(IEventAggregator events, DeviceManager deviceManager)
{
@@ -37,6 +40,8 @@ namespace Artemis.ViewModels.Profiles
_deviceManager = deviceManager;
PreviewTimer = new Timer(40);
+ ShowAll = false;
+
PreviewTimer.Elapsed += InvokeUpdateKeyboardPreview;
}
@@ -76,6 +81,17 @@ namespace Artemis.ViewModels.Profiles
}
}
+ public bool ShowAll
+ {
+ get { return _showAll; }
+ set
+ {
+ if (value == _showAll) return;
+ _showAll = value;
+ NotifyOfPropertyChange(() => ShowAll);
+ }
+ }
+
public ImageSource KeyboardImage => ImageUtilities
.BitmapToBitmapImage(_deviceManager.ActiveKeyboard?.PreviewSettings.Image ?? Resources.none);
@@ -93,7 +109,7 @@ namespace Artemis.ViewModels.Profiles
_blurProgress = _blurProgress + 0.025;
BlurRadius = (Math.Sin(_blurProgress*Math.PI) + 1)*10 + 10;
- if (SelectedProfile == null || _deviceManager.ActiveKeyboard == null)
+ if (SelectedProfile == null || _deviceManager.ActiveKeyboard == null || (!ShowAll && SelectedLayer == null))
{
var preview = new DrawingImage();
preview.Freeze();
@@ -101,6 +117,7 @@ namespace Artemis.ViewModels.Profiles
return;
}
+
var keyboardRect = _deviceManager.ActiveKeyboard.KeyboardRectangle(4);
var visual = new DrawingVisual();
using (var drawingContext = visual.RenderOpen())
@@ -109,8 +126,10 @@ namespace Artemis.ViewModels.Profiles
drawingContext.PushClip(new RectangleGeometry(keyboardRect));
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
+ // Get the layers that must be drawn
+ var drawLayers = GetRenderLayers();
+
// Draw the layers
- var drawLayers = SelectedProfile.GetRenderLayers(new ProfilePreviewDataModel(), false, true);
foreach (var layer in drawLayers)
{
layer.Update(null, true, false);
@@ -121,7 +140,12 @@ namespace Artemis.ViewModels.Profiles
// Get the selection color
var accentColor = ThemeManager.DetectAppStyle(Application.Current)?.Item2?.Resources["AccentColor"];
if (accentColor == null)
+ {
+ var preview = new DrawingImage();
+ preview.Freeze();
+ KeyboardPreview = preview;
return;
+ }
var pen = new Pen(new SolidColorBrush((Color) accentColor), 0.4);
@@ -199,8 +223,7 @@ namespace Artemis.ViewModels.Profiles
var x = pos.X/((double) keyboard.PreviewSettings.Width/keyboard.Width);
var y = pos.Y/((double) keyboard.PreviewSettings.Height/keyboard.Height);
- var hoverLayer = SelectedProfile.GetLayers()
- .Where(l => l.MustDraw())
+ var hoverLayer = GetLayers().Where(l => l.MustDraw())
.FirstOrDefault(l => l.Properties.GetRect(1).Contains(x, y));
SelectedLayer = hoverLayer;
@@ -219,8 +242,7 @@ namespace Artemis.ViewModels.Profiles
var keyboard = _deviceManager.ActiveKeyboard;
var x = pos.X/((double) keyboard.PreviewSettings.Width/keyboard.Width);
var y = pos.Y/((double) keyboard.PreviewSettings.Height/keyboard.Height);
- var hoverLayer = SelectedProfile.GetLayers()
- .Where(l => l.MustDraw())
+ var hoverLayer = GetLayers().Where(l => l.MustDraw())
.FirstOrDefault(l => l.Properties.GetRect(1).Contains(x, y));
HandleDragging(e, x, y, hoverLayer);
@@ -309,6 +331,39 @@ namespace Artemis.ViewModels.Profiles
}
}
+ public List GetRenderLayers()
+ {
+ // Get the layers that must be drawn
+ List drawLayers;
+ if (ShowAll)
+ return SelectedProfile.GetRenderLayers(new ProfilePreviewDataModel(), false, true);
+
+ if (SelectedLayer == null)
+ return new EditableList();
+
+ if (SelectedLayer.LayerType is FolderType)
+ drawLayers = SelectedLayer.GetRenderLayers(new ProfilePreviewDataModel(), false, true);
+ else
+ drawLayers = new List {SelectedLayer};
+
+ return drawLayers;
+ }
+
+
+ private List GetLayers()
+ {
+ // Get the layers that must be drawn
+ List drawLayers;
+ if (ShowAll)
+ drawLayers = SelectedProfile.GetLayers();
+ else if (SelectedLayer.LayerType is FolderType)
+ drawLayers = SelectedLayer.GetLayers().ToList();
+ else
+ drawLayers = new List { SelectedLayer };
+
+ return drawLayers;
+ }
+
#endregion
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml b/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml
index c49fedda6..9d98bfff7 100644
--- a/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml
+++ b/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml
@@ -113,7 +113,7 @@
-
-
+
+
+
+
+
+
-
+
@@ -13,14 +13,14 @@
-
+
-
-
-
+
+
+
\ No newline at end of file
diff --git a/Artemis/UT2Artemis/UT2Artemis.vcxproj b/Artemis/UT2Artemis/UT2Artemis.vcxproj
new file mode 100644
index 000000000..69b4ec658
--- /dev/null
+++ b/Artemis/UT2Artemis/UT2Artemis.vcxproj
@@ -0,0 +1,153 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {CF766633-768F-4A74-AA27-FF7D81191D76}
+ Win32Proj
+ UT2Artemis
+ 8.1
+
+
+
+ DynamicLibrary
+ true
+ v140
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v140
+ true
+ Unicode
+
+
+ DynamicLibrary
+ true
+ v140
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v140
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+ false
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;UT2ARTEMIS_EXPORTS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+
+
+
+
+
+
+ Level3
+ Disabled
+ _DEBUG;_WINDOWS;_USRDLL;UT2ARTEMIS_EXPORTS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;UT2ARTEMIS_EXPORTS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ NDEBUG;_WINDOWS;_USRDLL;UT2ARTEMIS_EXPORTS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/UT2Artemis/UT2Artemis.vcxproj.filters b/Artemis/UT2Artemis/UT2Artemis.vcxproj.filters
new file mode 100644
index 000000000..6a1782f7d
--- /dev/null
+++ b/Artemis/UT2Artemis/UT2Artemis.vcxproj.filters
@@ -0,0 +1,17 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
\ No newline at end of file
diff --git a/Artemis/UnrealTournament2Artemis/Artemis.uplugin b/Artemis/UnrealTournament2Artemis/Artemis.uplugin
new file mode 100644
index 000000000..8ea2a6467
--- /dev/null
+++ b/Artemis/UnrealTournament2Artemis/Artemis.uplugin
@@ -0,0 +1,21 @@
+{
+ "Version" : 1,
+ "FileVersion": 3,
+ "FriendlyName": "Artemis Plugin",
+ "VersionName": "1.0",
+ "CreatedBy": "Robert Beekman",
+ "CreatedByURL": "https://github.com/SpoinkyNL/Artemis",
+ "EngineVersion": "4.4.0",
+ "Description": "Communicates with Artemis to let the main program know what's happening ingame",
+ "Category": "UnrealTournament.Mod",
+ "EnabledByDefault": true,
+ "CanContainContent": false,
+
+ "Modules": [
+ {
+ "Name": "Artemis",
+ "Type": "Runtime",
+ "WhitelistPlatforms": [ "Win32", "Win64" ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Artemis/UnrealTournament2Artemis/Binaries/Win64/UE4-Artemis-Win64-Shipping.dll b/Artemis/UnrealTournament2Artemis/Binaries/Win64/UE4-Artemis-Win64-Shipping.dll
new file mode 100644
index 000000000..87c719160
Binary files /dev/null and b/Artemis/UnrealTournament2Artemis/Binaries/Win64/UE4-Artemis-Win64-Shipping.dll differ
diff --git a/Artemis/UnrealTournament2Artemis/Binaries/Win64/UE4-Win64-Shipping.modules b/Artemis/UnrealTournament2Artemis/Binaries/Win64/UE4-Win64-Shipping.modules
new file mode 100644
index 000000000..a577932a1
--- /dev/null
+++ b/Artemis/UnrealTournament2Artemis/Binaries/Win64/UE4-Win64-Shipping.modules
@@ -0,0 +1,8 @@
+{
+ "Changelist" : 2897679,
+ "BuildId" : "5a8ef5b7-c9bb-42bd-ab7c-fb8e33f704ec",
+ "Modules" :
+ {
+ "Artemis" : "UE4-Artemis-Win64-Shipping.dll"
+ }
+}
\ No newline at end of file
diff --git a/Artemis/UnrealTournament2Artemis/Source/Artemis.Build.cs b/Artemis/UnrealTournament2Artemis/Source/Artemis.Build.cs
new file mode 100644
index 000000000..54660fe05
--- /dev/null
+++ b/Artemis/UnrealTournament2Artemis/Source/Artemis.Build.cs
@@ -0,0 +1,23 @@
+using System.IO;
+
+namespace UnrealBuildTool.Rules
+{
+ public class Artemis : ModuleRules
+ {
+ public Artemis(TargetInfo Target)
+ {
+ PublicDependencyModuleNames.AddRange(
+ new string[]
+ {
+ "Core",
+ "CoreUObject",
+ "Engine",
+ "UnrealTournament",
+ "InputCore",
+ "SlateCore",
+ "Json"
+ }
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/UnrealTournament2Artemis/Source/Private/Artemis.cpp b/Artemis/UnrealTournament2Artemis/Source/Private/Artemis.cpp
new file mode 100644
index 000000000..3680cf068
--- /dev/null
+++ b/Artemis/UnrealTournament2Artemis/Source/Private/Artemis.cpp
@@ -0,0 +1,225 @@
+// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
+
+#include "Artemis.h"
+
+#include "UnrealTournament.h"
+#include "UTPlayerController.h"
+#include "UTGameState.h"
+#include "UTArmor.h"
+#include "UTTimedPowerup.h"
+
+DEFINE_LOG_CATEGORY_STATIC(LogUTKBLightShow, Log, All);
+
+AArtemis::AArtemis(const FObjectInitializer& ObjectInitializer)
+ : Super(ObjectInitializer)
+{
+}
+
+FArtemis::FArtemis()
+{
+ FrameTimeMinimum = 0.03f;
+ DeltaTimeAccumulator = 0;
+}
+
+IMPLEMENT_MODULE(FArtemis, Artemis)
+
+void FArtemis::StartupModule()
+{
+ WritePipe(FString(TEXT("Unreal Tournament plugin loaded")));
+}
+
+void FArtemis::ShutdownModule()
+{
+
+}
+
+void FArtemis::Tick(float DeltaTime)
+{
+ if (GIsEditor)
+ {
+ return;
+ }
+
+ // Avoid double ticking
+ if (LastFrameCounter > 0 && LastFrameCounter == GFrameCounter)
+ {
+ return;
+ }
+
+ LastFrameCounter = GFrameCounter;
+
+ // We may be going 120hz, don't spam the device
+ DeltaTimeAccumulator += DeltaTime;
+ if (DeltaTimeAccumulator < FrameTimeMinimum)
+ {
+ return;
+ }
+ DeltaTimeAccumulator = 0;
+
+ // Setup JSON object
+ TSharedRef RootJson(new FJsonObject());
+ TSharedRef PlayerJson(new FJsonObject());
+ TSharedRef EnvironmentJson(new FJsonObject());
+ RootJson->SetObjectField("Player", PlayerJson);
+ RootJson->SetObjectField("Environment", EnvironmentJson);
+ // Setup JSON writer to be used before returning
+ FString Buffer;
+ TSharedRef > Writer = TJsonWriterFactory<>::Create(&Buffer);
+
+ AUTPlayerController* UTPC = nullptr;
+ AUTGameState* GS = nullptr;
+ const TIndirectArray& AllWorlds = GEngine->GetWorldContexts();
+ for (const FWorldContext& Context : AllWorlds)
+ {
+ UWorld* World = Context.World();
+ if (World && World->WorldType == EWorldType::Game)
+ {
+ UTPC = Cast(GEngine->GetFirstLocalPlayerController(World));
+ if (UTPC)
+ {
+ UUTLocalPlayer* UTLP = Cast(UTPC->GetLocalPlayer());
+ if (UTLP == nullptr || UTLP->IsMenuGame())
+ {
+ UTPC = nullptr;
+ continue;
+ }
+
+ GS = World->GetGameState();
+ break;
+ }
+ }
+ }
+
+ if (!UTPC || !GS)
+ {
+ RootJson->SetStringField("State", "MainMenu");
+ FJsonSerializer::Serialize(RootJson, Writer);
+ WritePipe(Buffer);
+ return;
+ }
+
+ // Update environment data
+ if (GS->GetGameModeClass())
+ {
+ EnvironmentJson->SetStringField("GameMode", GS->GetGameModeClass()->GetName());
+ }
+ EnvironmentJson->SetBoolField("MatchStarted", GS->HasMatchStarted());
+ EnvironmentJson->SetNumberField("GoalScore", GS->GoalScore);
+ // Insert GameState JsonReport
+ GS->MakeJsonReport(EnvironmentJson);
+ // The JsonReport may contain all players, which is a bit too much
+ if (EnvironmentJson->HasField("Players"))
+ {
+ EnvironmentJson->RemoveField("Players");
+ }
+
+ // Update player data
+ // If character not found player must be spectating(?)
+ if (!UTPC->GetUTCharacter())
+ {
+ RootJson->SetStringField("State", "Spectating");
+ }
+ // If dead, don't try reading HP/Armor
+ else if (UTPC->GetUTCharacter()->IsDead())
+ {
+ RootJson->SetStringField("State", "Dead");
+ PlayerJson->SetNumberField("Health", 0);
+ PlayerJson->SetNumberField("Armor", 0);
+ }
+ // Player is found and alive
+ else
+ {
+ // Update HP and armor
+ RootJson->SetStringField("State", "Alive");
+ PlayerJson->SetNumberField("Health", UTPC->GetUTCharacter()->Health);
+ PlayerJson->SetNumberField("Armor", UTPC->GetUTCharacter()->ArmorAmount);
+
+ // Update player powerups data
+ TSharedRef InventoryJson(new FJsonObject());
+ PlayerJson->SetObjectField("Inventory", InventoryJson);
+ InventoryJson->SetBoolField("HasJumpBoots", false);
+ InventoryJson->SetBoolField("HasInvisibility", false);
+ InventoryJson->SetBoolField("HasBerserk", false);
+ InventoryJson->SetBoolField("HasUDamage", false);
+ InventoryJson->SetBoolField("HasThighPads", false);
+ InventoryJson->SetBoolField("HasShieldBelt", false);
+ InventoryJson->SetBoolField("HasChestArmor", false);
+ InventoryJson->SetBoolField("HasHelmet", false);
+
+ for (TInventoryIterator<> It(UTPC->GetUTCharacter()); It; ++It)
+ {
+ AUTInventory* InventoryItem = (*It);
+ // Using Contains here because pickups might have slighty different names in different contexts
+ if (InventoryItem->GetClass()->GetName().Contains("Armor_ThighPads"))
+ {
+ InventoryJson->SetBoolField("HasThighPads", true);
+ }
+ else if (InventoryItem->GetClass()->GetName().Contains("Armor_ShieldBelt"))
+ {
+ InventoryJson->SetBoolField("HasShieldBelt", true);
+ }
+ else if (InventoryItem->GetClass()->GetName().Contains("Armor_Chest"))
+ {
+ InventoryJson->SetBoolField("HasChestArmor", true);
+ }
+ else if (InventoryItem->GetClass()->GetName().Contains("Armor_Helmet"))
+ {
+ InventoryJson->SetBoolField("HasHelmet", true);
+ }
+ else if (InventoryItem->GetClass()->GetName().Contains("JumpBoots"))
+ {
+ InventoryJson->SetBoolField("HasJumpBoots", true);
+ }
+ else if (InventoryItem->GetClass()->GetName().Contains("Invis"))
+ {
+ InventoryJson->SetBoolField("HasInvisibility", true);
+ }
+ else if (InventoryItem->GetClass()->GetName().Contains("Berserk"))
+ {
+ InventoryJson->SetBoolField("HasBerserk", true);
+ }
+ else if (InventoryItem->GetClass()->GetName().Contains("UDamage"))
+ {
+ InventoryJson->SetBoolField("HasUDamage", true);
+ }
+ }
+
+ // Update player weapon data
+ TSharedRef WeaponJson(new FJsonObject());
+ PlayerJson->SetObjectField("Weapon", WeaponJson);
+ if (UTPC->GetUTCharacter()->GetWeapon())
+ {
+ WeaponJson->SetStringField("Name", UTPC->GetUTCharacter()->GetWeapon()->GetClass()->GetName());
+ WeaponJson->SetNumberField("Ammo", UTPC->GetUTCharacter()->GetWeapon()->Ammo);
+ WeaponJson->SetNumberField("MaxAmmo", UTPC->GetUTCharacter()->GetWeapon()->MaxAmmo);
+ WeaponJson->SetBoolField("IsFiring", UTPC->GetUTCharacter()->GetWeapon()->IsFiring());
+ WeaponJson->SetNumberField("FireMode", UTPC->GetUTCharacter()->GetWeapon()->GetCurrentFireMode());
+ WeaponJson->SetNumberField("ZoomState", UTPC->GetUTCharacter()->GetWeapon()->ZoomState);
+ }
+ else {
+ WeaponJson->SetStringField("Name", "None");
+ }
+ }
+ // Insert PlayerState JsonReport
+ TSharedRef PlayerStateJson(new FJsonObject());
+ PlayerJson->SetObjectField("State", PlayerStateJson);
+ if (UTPC->UTPlayerState)
+ {
+ UTPC->UTPlayerState->MakeJsonReport(PlayerStateJson);
+ }
+
+ FJsonSerializer::Serialize(RootJson, Writer);
+ WritePipe(Buffer);
+}
+
+void FArtemis::WritePipe(FString msg)
+{
+ pipe = CreateFile(TEXT("\\\\.\\pipe\\artemis"), GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
+ if (pipe == nullptr || pipe == INVALID_HANDLE_VALUE)
+ {
+ return;
+ }
+
+ uint32 BytesWritten = 0;
+ WriteFile(pipe, TCHAR_TO_ANSI(*msg), msg.Len(), (::DWORD*)&BytesWritten, nullptr);
+}
\ No newline at end of file
diff --git a/Artemis/UnrealTournament2Artemis/Source/Private/Artemis.h b/Artemis/UnrealTournament2Artemis/Source/Private/Artemis.h
new file mode 100644
index 000000000..2ca2f51e9
--- /dev/null
+++ b/Artemis/UnrealTournament2Artemis/Source/Private/Artemis.h
@@ -0,0 +1,41 @@
+// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
+#pragma once
+
+#include "Core.h"
+#include "UnrealTournament.h"
+#include "JsonSerializer.h"
+#include "JsonObject.h"
+#include "JsonReader.h"
+
+#include "Artemis.generated.h"
+
+UCLASS(Blueprintable, Meta = (ChildCanTick))
+class AArtemis : public AActor
+{
+ GENERATED_UCLASS_BODY()
+
+};
+
+struct FArtemis : FTickableGameObject, IModuleInterface
+{
+ FArtemis();
+ virtual void Tick(float DeltaTime) override;
+ virtual bool IsTickable() const override { return true; }
+ virtual bool IsTickableInEditor() const override { return true; }
+ virtual bool IsTickableWhenPaused() const override { return true; }
+
+ virtual void StartupModule() override;
+ virtual void ShutdownModule() override;
+
+ // Put a real stat id here
+ virtual TStatId GetStatId() const
+ {
+ return TStatId();
+ }
+
+ void WritePipe(FString msg);
+ HANDLE pipe;
+ float DeltaTimeAccumulator;
+ float FrameTimeMinimum;
+ uint64 LastFrameCounter;
+};
\ No newline at end of file
diff --git a/Artemis/UnrealTournament2Artemis/UnrealTournament2Artemis.vcxproj b/Artemis/UnrealTournament2Artemis/UnrealTournament2Artemis.vcxproj
new file mode 100644
index 000000000..b4cd9703f
--- /dev/null
+++ b/Artemis/UnrealTournament2Artemis/UnrealTournament2Artemis.vcxproj
@@ -0,0 +1,165 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {3541864F-1662-4BD6-8328-2C87AE61D152}
+ Win32Proj
+ UnrealTournament2Artemis
+ 8.1
+
+
+
+ DynamicLibrary
+ true
+ v140
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v140
+ true
+ Unicode
+
+
+ DynamicLibrary
+ true
+ v140
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v140
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+ false
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;UNREALTOURNAMENT2ARTEMIS_EXPORTS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+
+
+
+
+
+
+ Level3
+ Disabled
+ _DEBUG;_WINDOWS;_USRDLL;UNREALTOURNAMENT2ARTEMIS_EXPORTS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;UNREALTOURNAMENT2ARTEMIS_EXPORTS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ NDEBUG;_WINDOWS;_USRDLL;UNREALTOURNAMENT2ARTEMIS_EXPORTS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/UnrealTournament2Artemis/UnrealTournament2Artemis.vcxproj.filters b/Artemis/UnrealTournament2Artemis/UnrealTournament2Artemis.vcxproj.filters
new file mode 100644
index 000000000..256e298e2
--- /dev/null
+++ b/Artemis/UnrealTournament2Artemis/UnrealTournament2Artemis.vcxproj.filters
@@ -0,0 +1,45 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Artemis/UnrealTournament2Artemis/ut-plugin.zip b/Artemis/UnrealTournament2Artemis/ut-plugin.zip
new file mode 100644
index 000000000..c013a0f6f
Binary files /dev/null and b/Artemis/UnrealTournament2Artemis/ut-plugin.zip differ