Compare commits

6 Commits
v2.2 ... master

Author SHA1 Message Date
c249c8b660 Use harmony instead of custom patcher
Cleanup code from decompiler
2024-11-06 10:15:39 -05:00
StalkR
c05d904954 github workflows: upgrade DepotDownloader 2.5.0->2.7.2 2024-10-07 01:54:13 +02:00
StalkR
705601d693 build action: allow workflow dispatch 2024-05-13 19:52:00 +02:00
StalkR
b476132ec9 readme: reference plugin definition in plugin hub 2024-04-21 11:29:52 +02:00
StalkR
27bd54ed5b github workflows for build 2024-04-21 11:25:24 +02:00
StalkR
32fc39deb8 upgrade csproj to new .NET SDK syntax, remove sln 2024-04-21 11:24:54 +02:00
9 changed files with 180 additions and 462 deletions

0
.github/workflows/build.todo vendored Normal file
View File

2
.gitignore vendored
View File

@@ -388,4 +388,4 @@ FodyWeavers.xsd
*.sln.iml
# Junction to SpaceEngineers
GameBinaries
.GameBinaries

View File

@@ -1,173 +0,0 @@
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
namespace ClientPlugin
{
public static class MethodUtil
{
public static void SwapMethod(MethodBase source, MethodBase dest)
{
bool flag = !MethodUtil.MethodSignaturesEqual(source, dest);
if (flag)
{
throw new ArgumentException("The method signatures are not the same.", "source");
}
MethodUtil.SwapMethod(MethodUtil.GetMethodAddress(source), dest);
}
public unsafe static void SwapMethod(IntPtr srcAdr, MethodBase dest)
{
IntPtr methodAddress = MethodUtil.GetMethodAddress(dest);
bool flag = IntPtr.Size == 8;
if (flag)
{
ulong* ptr = (ulong*)srcAdr.ToPointer();
ulong* ptr2 = (ulong*)methodAddress.ToPointer();
ulong num = *ptr;
*ptr = *ptr2;
*ptr2 = num;
}
else
{
uint* ptr3 = (uint*)methodAddress.ToPointer();
uint* ptr4 = (uint*)srcAdr.ToPointer();
uint num2 = *ptr4;
*ptr4 = *ptr3;
*ptr3 = num2;
}
}
public static void ReplaceMethod(MethodBase source, MethodBase dest)
{
bool flag = !MethodUtil.MethodSignaturesEqual(source, dest);
if (flag)
{
throw new ArgumentException("The method signatures are not the same.", "source");
}
MethodUtil.ReplaceMethod(MethodUtil.GetMethodAddress(source), dest);
}
public unsafe static void ReplaceMethod(IntPtr srcAdr, MethodBase dest)
{
IntPtr methodAddress = MethodUtil.GetMethodAddress(dest);
bool flag = IntPtr.Size == 8;
if (flag)
{
ulong* ptr = (ulong*)methodAddress.ToPointer();
*ptr = (ulong)(*(long*)srcAdr.ToPointer());
}
else
{
uint* ptr2 = (uint*)methodAddress.ToPointer();
*ptr2 = *(uint*)srcAdr.ToPointer();
}
}
public unsafe static IntPtr GetMethodAddress(MethodBase method)
{
bool flag = method is DynamicMethod;
IntPtr intPtr;
if (flag)
{
intPtr = MethodUtil.GetDynamicMethodAddress(method);
}
else
{
RuntimeHelpers.PrepareMethod(method.MethodHandle);
intPtr = new IntPtr((void*)((byte*)method.MethodHandle.Value.ToPointer() + 8L));
}
return intPtr;
}
private unsafe static IntPtr GetDynamicMethodAddress(MethodBase method)
{
byte* ptr = (byte*)MethodUtil.GetDynamicMethodRuntimeHandle(method).Value.ToPointer();
bool flag = IntPtr.Size == 8;
IntPtr intPtr;
if (flag)
{
ulong* ptr2 = (ulong*)ptr;
ptr2 += 6;
intPtr = new IntPtr((void*)ptr2);
}
else
{
uint* ptr3 = (uint*)ptr;
ptr3 += 6;
intPtr = new IntPtr((void*)ptr3);
}
return intPtr;
}
private static RuntimeMethodHandle GetDynamicMethodRuntimeHandle(MethodBase method)
{
bool flag = method is DynamicMethod;
if (flag)
{
FieldInfo field = typeof(DynamicMethod).GetField("m_method", BindingFlags.Instance | BindingFlags.NonPublic);
bool flag2 = field != null;
if (flag2)
{
return (RuntimeMethodHandle)field.GetValue(method);
}
}
return method.MethodHandle;
}
private static bool MethodSignaturesEqual(MethodBase x, MethodBase y)
{
bool flag = x.CallingConvention != y.CallingConvention;
bool flag2;
if (flag)
{
flag2 = false;
}
else
{
Type methodReturnType = MethodUtil.GetMethodReturnType(x);
Type methodReturnType2 = MethodUtil.GetMethodReturnType(y);
bool flag3 = methodReturnType != methodReturnType2;
if (flag3)
{
flag2 = false;
}
else
{
ParameterInfo[] parameters = x.GetParameters();
ParameterInfo[] parameters2 = y.GetParameters();
bool flag4 = parameters.Length != parameters2.Length;
if (flag4)
{
flag2 = false;
}
else
{
for (int i = 0; i < parameters.Length; i++)
{
bool flag5 = parameters[i].ParameterType != parameters2[i].ParameterType;
if (flag5)
{
return false;
}
}
flag2 = true;
}
}
}
return flag2;
}
private static Type GetMethodReturnType(MethodBase method)
{
MethodInfo methodInfo = method as MethodInfo;
bool flag = methodInfo == null;
if (flag)
{
throw new ArgumentException("Unsupported MethodBase : " + method.GetType().Name, "method");
}
return methodInfo.ReturnType;
}
}
}

View File

@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TimeoutFix")]
[assembly: AssemblyDescription("A plugin to fix the server is not responding error")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TimeoutFix")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("D3C01D03-D271-4840-9C08-A86420E04606")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -14,11 +14,12 @@ and released on [reddit][reddit] with the source.
Later versions of the plugin were distributed in binary form (dll) among the
Space Engineers community but, to our knowledge, without source.
The purpose of this repository is to present the source of the latest known
version of the plugin, for inclusion in the [Plugin Hub][pluginhub] of
[Plugin Loader][pluginloader].
version of the plugin, for [inclusion][pluginhub-def] in the
[Plugin Hub][pluginhub] of [Plugin Loader][pluginloader].
[pluginloader]: https://github.com/sepluginloader/PluginLoader
[pluginhub]: https://github.com/sepluginloader/PluginHub
[pluginloader]: https://github.com/sepluginloader/PluginLoader
[pluginhub-def]: https://github.com/sepluginloader/PluginHub/blob/main/Plugins/TimeoutFix.xml
## Credits

View File

@@ -1,11 +1,12 @@
:: This script creates a symlink to the game binaries to account for different installation directories on different systems.
:: Create junctions (symlinks) to binary references to account for different installation directories on different systems.
:: Use the dot (.) prefix so dotnet ignores the folder during build.
@echo off
set /p path="Please enter the folder location of your SpaceEngineers.exe or SpaceEngineersDedicated.exe: "
cd %~dp0
rmdir GameBinaries > nul 2>&1
mklink /J GameBinaries "%path%"
rmdir .GameBinaries > nul 2>&1
mklink /J .GameBinaries "%path%"
if errorlevel 1 goto Error
echo Done!

View File

@@ -1,8 +1,7 @@
using System;
using System.Diagnostics;
using System.Diagnostics;
using System.Reflection;
using System.Text;
using ClientPlugin;
using HarmonyLib;
using Sandbox;
using Sandbox.Engine.Multiplayer;
using Sandbox.Engine.Networking;
@@ -17,20 +16,24 @@ using VRage.GameServices;
using VRage.Plugins;
using VRage.Utils;
namespace TimeoutFixPlugin
namespace TimeoutFix;
public class TimeoutFix : IPlugin
{
public class TimeoutFix : IPlugin, IDisposable
private const string Version = "v2.2";
private static readonly MethodInfo Target = typeof(MyJoinGameHelper).GetMethod(nameof(DownloadWorld), BindingFlags.Static | BindingFlags.NonPublic);
private static readonly MethodInfo Patch = typeof(TimeoutFix).GetMethod(nameof(DownloadWorld), BindingFlags.Static | BindingFlags.NonPublic);
private static readonly MethodInfo ReceiveTarget = typeof(MyJoinGameHelper).GetMethod(nameof(WorldReceived), BindingFlags.Static | BindingFlags.Public);
private static readonly MethodInfo ReceivePatch = typeof(TimeoutFix).GetMethod(nameof(WorldReceived), BindingFlags.Static | BindingFlags.NonPublic);
private static readonly FieldInfo ProgressField = typeof(MyJoinGameHelper).GetField("m_progress", BindingFlags.Static | BindingFlags.NonPublic);
private static bool _worldReceived;
private static MyGuiScreenProgressBase Progress
{
private static MyGuiScreenProgressBase m_progress
{
get
{
return (MyGuiScreenProgressBase)((MyGuiScreenProgressBase)TimeoutFix._progressField.GetValue(null));
}
set
{
TimeoutFix._progressField.SetValue(null, value);
}
get => (MyGuiScreenProgressBase)ProgressField.GetValue(null);
set => ProgressField.SetValue(null, value);
}
public void Dispose()
@@ -39,167 +42,134 @@ namespace TimeoutFixPlugin
public void Init(object gameInstance)
{
MethodUtil.ReplaceMethod(TimeoutFix._patch, TimeoutFix._target);
MethodUtil.ReplaceMethod(TimeoutFix._receivePatch, TimeoutFix._receiveTarget);
var harmony = new Harmony(nameof(TimeoutFix));
harmony.Patch(Target, new HarmonyMethod(Patch));
harmony.Patch(ReceiveTarget, new HarmonyMethod(ReceivePatch));
}
public void Update()
{
}
private static void DownloadWorld(MyGuiScreenProgress progress, MyMultiplayerBase multiplayer)
private static bool DownloadWorld(MyGuiScreenProgress progress, MyMultiplayerBase multiplayer)
{
TimeoutFix._worldReceived = false;
bool flag = progress.Text != null;
if (flag)
_worldReceived = false;
if (progress.Text != null)
{
progress.Text.Clear();
progress.Text.Append(MyTexts.Get(MyCommonTexts.MultiplayerStateConnectingToServer));
}
MyLog.Default.WriteLine("World requested: Timeout fix v2.2");
Stopwatch worldRequestTime = Stopwatch.StartNew();
ulong serverId = multiplayer.GetOwner();
bool connected = false;
MyLog.Default.WriteLine($"World requested: Timeout fix {Version}");
var worldRequestTime = Stopwatch.StartNew();
var serverId = multiplayer.GetOwner();
var connected = false;
progress.Tick += delegate
{
MyP2PSessionState myP2PSessionState = default(MyP2PSessionState);
var myP2PSessionState = default(MyP2PSessionState);
MyGameService.Peer2Peer.GetSessionState(multiplayer.ServerId, ref myP2PSessionState);
bool flag2 = !connected && myP2PSessionState.ConnectionActive;
if (flag2)
if (!connected && myP2PSessionState.ConnectionActive)
{
MyLog.Default.WriteLine("World requested - connection alive");
connected = true;
bool flag3 = progress.Text != null;
if (flag3)
if (progress.Text != null)
{
progress.Text.Clear();
progress.Text.AppendLine("Using Rexxar's fixed join code v2.2! :D");
progress.Text.Append(MyTexts.Get(MyCommonTexts.MultiplayerStateWaitingForServer));
}
}
bool flag4 = connected && !myP2PSessionState.ConnectionActive;
if (flag4)
if (connected && !myP2PSessionState.ConnectionActive)
{
MyLog.Default.WriteLine("World request - connection dropped");
progress.Cancel();
MyGuiSandbox.Show(MyCommonTexts.MultiplaterJoin_ServerIsNotResponding, default(MyStringId), MyMessageBoxStyleEnum.Error);
MyGuiSandbox.Show(MyCommonTexts.MultiplaterJoin_ServerIsNotResponding, default, MyMessageBoxStyleEnum.Error);
MySessionLoader.UnloadAndExitToMenu();
}
bool flag5 = MyScreenManager.IsScreenOnTop((MyGuiScreenBase)progress);
bool flag6 = serverId != multiplayer.GetOwner();
if (flag6)
var progressScreenOnTop = MyScreenManager.IsScreenOnTop(progress);
if (serverId != multiplayer.GetOwner())
{
MyLog.Default.WriteLine(string.Format("World requested - failed, server changed: Expected {0} got {1}", serverId, multiplayer.GetOwner()));
progress.Cancel();
MyGuiSandbox.Show(MyCommonTexts.MultiplayerErrorServerHasLeft, default(MyStringId), MyMessageBoxStyleEnum.Error);
MyGuiSandbox.Show(MyCommonTexts.MultiplayerErrorServerHasLeft, default, MyMessageBoxStyleEnum.Error);
multiplayer.Dispose();
}
bool flag7 = MyScreenManager.IsScreenOfTypeOpen(typeof(MyGuiScreenDownloadMods));
bool flag8 = !flag7 && flag5 && !worldRequestTime.IsRunning;
if (flag8)
var downloadScreenOpen = MyScreenManager.IsScreenOfTypeOpen(typeof(MyGuiScreenDownloadMods));
if (!downloadScreenOpen && progressScreenOnTop && !worldRequestTime.IsRunning)
{
worldRequestTime.Start();
}
else
{
bool flag9 = flag7 || (!flag5 && worldRequestTime.IsRunning);
if (flag9)
{
if (downloadScreenOpen || !progressScreenOnTop && worldRequestTime.IsRunning)
worldRequestTime.Stop();
}
}
bool flag10 = flag7 && progress.Visible;
if (flag10)
if (downloadScreenOpen && progress.Visible)
{
progress.HideScreen();
}
else
{
bool flag11 = !flag7 && !progress.Visible;
if (flag11)
{
if (!downloadScreenOpen && !progress.Visible)
progress.UnhideScreen();
}
}
bool flag12 = !TimeoutFix._worldReceived && worldRequestTime.IsRunning && (float)(worldRequestTime.ElapsedTicks / Stopwatch.Frequency) > 120f;
if (flag12)
if (!_worldReceived && worldRequestTime.IsRunning && worldRequestTime.ElapsedTicks / Stopwatch.Frequency > 120f)
{
MyLog.Default.WriteLine("World requested - failed, timeout reached");
MyLog.Default.WriteLine(string.Format("Elapsed : {0:N2}", worldRequestTime.ElapsedTicks / Stopwatch.Frequency));
progress.Cancel();
MyGuiSandbox.Show(MyCommonTexts.MultiplaterJoin_ServerIsNotResponding, default(MyStringId), MyMessageBoxStyleEnum.Error);
MyGuiSandbox.Show(MyCommonTexts.MultiplaterJoin_ServerIsNotResponding, default, MyMessageBoxStyleEnum.Error);
MySessionLoader.UnloadAndExitToMenu();
}
};
multiplayer.DownloadWorld(MyFinalBuildConstants.APP_VERSION.Version);
return false;
}
private static void CheckDx11AndJoin(MyObjectBuilder_World world, MyMultiplayerBase multiplayer)
{
bool scenario = multiplayer.Scenario;
if (scenario)
{
if (multiplayer.Scenario)
MySessionLoader.LoadMultiplayerScenarioWorld(world, multiplayer);
}
else
{
MySessionLoader.LoadMultiplayerSession(world, multiplayer);
}
}
private static void WorldReceived(MyObjectBuilder_World world, MyMultiplayerBase multiplayer)
private static bool WorldReceived(MyObjectBuilder_World world, MyMultiplayerBase multiplayer)
{
bool flag = world == null;
if (flag)
if (world == null)
{
MyLog.Default.WriteLine("World requested - failed, version mismatch");
TimeoutFix.m_progress.Cancel();
TimeoutFix.m_progress = null;
MyGuiSandbox.Show(MyCommonTexts.MultiplayerErrorAppVersionMismatch, default(MyStringId), MyMessageBoxStyleEnum.Error);
Progress.Cancel();
Progress = null;
MyGuiSandbox.Show(MyCommonTexts.MultiplayerErrorAppVersionMismatch, default, MyMessageBoxStyleEnum.Error);
multiplayer.Dispose();
}
else
{
TimeoutFix._worldReceived = true;
_worldReceived = true;
MyLog.Default.WriteLine("World requested - world data received");
bool flag2;
if (world == null)
{
flag2 = null != null;
}
else
{
MyObjectBuilder_Checkpoint checkpoint = world.Checkpoint;
flag2 = ((checkpoint != null) ? checkpoint.Settings : null) != null;
}
bool flag3 = flag2 && !MySandboxGame.Config.ExperimentalMode;
if (flag3)
if (world.Checkpoint?.Settings != null && !MySandboxGame.Config.ExperimentalMode)
{
MySessionLoader.UnloadAndExitToMenu();
StringBuilder stringBuilder = new StringBuilder();
var stringBuilder = new StringBuilder();
stringBuilder.AppendFormat(MyCommonTexts.DialogTextJoinWorldFailed, MyTexts.GetString(MyCommonTexts.MultiplayerErrorExperimental));
MyGuiSandbox.AddScreen((MyGuiScreenBase)MyGuiSandbox.CreateMessageBox(MyMessageBoxStyleEnum.Error, MyMessageBoxButtonsType.OK, stringBuilder, MyTexts.Get(MyCommonTexts.MessageBoxCaptionError), null, null, null, null, null, 0, MyGuiScreenMessageBox.ResultEnum.YES, true, null, true, null, true, false, null));
MyGuiSandbox.AddScreen(MyGuiSandbox.CreateMessageBox(MyMessageBoxStyleEnum.Error, MyMessageBoxButtonsType.OK, stringBuilder, MyTexts.Get(MyCommonTexts.MessageBoxCaptionError), null, null, null, null, null, 0, MyGuiScreenMessageBox.ResultEnum.YES, true, null, true, null, true, false, null));
}
else
{
TimeoutFix.m_progress = null;
TimeoutFix.CheckDx11AndJoin(world, multiplayer);
}
Progress = null;
CheckDx11AndJoin(world, multiplayer);
}
}
private static MethodInfo _target = typeof(MyJoinGameHelper).GetMethod("DownloadWorld", BindingFlags.Static | BindingFlags.NonPublic);
private static MethodInfo _patch = typeof(TimeoutFix).GetMethod("DownloadWorld", BindingFlags.Static | BindingFlags.NonPublic);
private static MethodInfo _receiveTarget = typeof(MyJoinGameHelper).GetMethod("WorldReceived", BindingFlags.Static | BindingFlags.Public);
private static MethodInfo _receivePatch = typeof(TimeoutFix).GetMethod("WorldReceived", BindingFlags.Static | BindingFlags.NonPublic);
private static bool _worldReceived;
private static readonly FieldInfo _progressField = typeof(MyJoinGameHelper).GetField("m_progress", BindingFlags.Static | BindingFlags.NonPublic);
private const string VERSION = "v2.2";
return false;
}
}

View File

@@ -1,66 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D3C01D03-D271-4840-9C08-A86420E04606}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TimeoutFix</RootNamespace>
<AssemblyName>TimeoutFix</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DebugType>none</DebugType>
<PdbPath>none</PdbPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Compile Include="ClientPlugin.cs" />
<Compile Include="TimeoutFix.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<PackageReference Include="CringePlugins" Version="0.1.32" />
</ItemGroup>
<ItemGroup>
<Reference Include="Sandbox.Game">
<HintPath>GameBinaries\Sandbox.Game.dll</HintPath>
</Reference>
<Reference Include="Sandbox.Graphics">
<HintPath>GameBinaries\Sandbox.Graphics.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="VRage">
<HintPath>GameBinaries\VRage.dll</HintPath>
</Reference>
<Reference Include="VRage.Game">
<HintPath>GameBinaries\VRage.Game.dll</HintPath>
</Reference>
<Reference Include="VRage.Library">
<HintPath>GameBinaries\VRage.Library.dll</HintPath>
</Reference>
<Reference Include="VRage.Math">
<HintPath>GameBinaries\VRage.Math.dll</HintPath>
</Reference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -1,9 +1,9 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29215.179
# Visual Studio Version 17
VisualStudioVersion = 17.11.35327.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TimeoutFix", "TimeoutFix.csproj", "{D3C01D03-D271-4840-9C08-A86420E04606}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimeoutFix", "TimeoutFix.csproj", "{3A616A98-0D6E-466D-8885-8D3A2E494753}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -11,15 +11,15 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D3C01D03-D271-4840-9C08-A86420E04606}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D3C01D03-D271-4840-9C08-A86420E04606}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D3C01D03-D271-4840-9C08-A86420E04606}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D3C01D03-D271-4840-9C08-A86420E04606}.Release|Any CPU.Build.0 = Release|Any CPU
{3A616A98-0D6E-466D-8885-8D3A2E494753}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3A616A98-0D6E-466D-8885-8D3A2E494753}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3A616A98-0D6E-466D-8885-8D3A2E494753}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3A616A98-0D6E-466D-8885-8D3A2E494753}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {363806C1-5B50-4D2A-B17D-8F738ABE3DC1}
SolutionGuid = {5CAAAB50-CF4A-4F5C-BF13-14F1F84F1753}
EndGlobalSection
EndGlobal