From 0930b2673903cfaa273c62e1e5e2154a26dd3567 Mon Sep 17 00:00:00 2001 From: Sophie Marie Date: Mon, 21 Nov 2022 12:23:02 -0800 Subject: [PATCH 01/85] Fix broken project locations In the .NET 4.8 solutions it was trying to get projects from ``G:\`` while .NET 4 solutions are getting them from the solutions root directory, I've updated them to get the 4.8 projects from the root directory and then load the 4.8 projects --- Novetus/Novetus.Net481.sln | 90 ++++++++++++++++---------------- Novetus/Novetus.Tools.Net481.sln | 62 +++++++++++----------- 2 files changed, 76 insertions(+), 76 deletions(-) diff --git a/Novetus/Novetus.Net481.sln b/Novetus/Novetus.Net481.sln index f0d9c9e..5ca7250 100644 --- a/Novetus/Novetus.Net481.sln +++ b/Novetus/Novetus.Net481.sln @@ -1,45 +1,45 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32630.192 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Novetus.Core", "NovetusCore\Novetus.Core.shproj", "{DEBCC57D-9A3B-4D7C-8693-FA4AEC56C8C1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Bootstrapper.Net481", "G:\Projects\GitHub\Novetus\Novetus_src\Novetus\Novetus.Bootstrapper\Novetus.Bootstrapper.Net481.csproj", "{8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Launcher.Net481", "G:\Projects\GitHub\Novetus\Novetus_src\Novetus\NovetusLauncher\Novetus.Launcher.Net481.csproj", "{78EE2921-681F-411A-90F2-773A5CE96B7E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.URI.Net481", "G:\Projects\GitHub\Novetus\Novetus_src\Novetus\NovetusURI\Novetus.URI.Net481.csproj", "{917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Release|Any CPU.Build.0 = Release|Any CPU - {78EE2921-681F-411A-90F2-773A5CE96B7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {78EE2921-681F-411A-90F2-773A5CE96B7E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {78EE2921-681F-411A-90F2-773A5CE96B7E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {78EE2921-681F-411A-90F2-773A5CE96B7E}.Release|Any CPU.Build.0 = Release|Any CPU - {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {66CA6CE5-670E-48AA-A2DA-9347371D4CA0} - EndGlobalSection - GlobalSection(SharedMSBuildProjectFiles) = preSolution - G:\Projects\GitHub\Novetus\Novetus_src\Novetus\NovetusCore\NovetusCore.projitems*{78ee2921-681f-411a-90f2-773a5ce96b7e}*SharedItemsImports = 4 - G:\Projects\GitHub\Novetus\Novetus_src\Novetus\NovetusCore\NovetusCore.projitems*{8d030e72-bbf0-42e2-9dfb-c29e9e2a7e80}*SharedItemsImports = 4 - G:\Projects\GitHub\Novetus\Novetus_src\Novetus\NovetusCore\NovetusCore.projitems*{917b30de-f2c0-4955-b3b9-5bf90c3d01e9}*SharedItemsImports = 4 - NovetusCore\NovetusCore.projitems*{debcc57d-9a3b-4d7c-8693-fa4aec56c8c1}*SharedItemsImports = 13 - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32901.82 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Novetus.Core", "NovetusCore\Novetus.Core.shproj", "{DEBCC57D-9A3B-4D7C-8693-FA4AEC56C8C1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Bootstrapper.Net481", "Novetus.Bootstrapper\Novetus.Bootstrapper.Net481.csproj", "{8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Launcher.Net481", "NovetusLauncher\Novetus.Launcher.Net481.csproj", "{78EE2921-681F-411A-90F2-773A5CE96B7E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.URI.Net481", "NovetusURI\Novetus.URI.Net481.csproj", "{917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + NovetusCore\NovetusCore.projitems*{78ee2921-681f-411a-90f2-773a5ce96b7e}*SharedItemsImports = 4 + NovetusCore\NovetusCore.projitems*{8d030e72-bbf0-42e2-9dfb-c29e9e2a7e80}*SharedItemsImports = 4 + NovetusCore\NovetusCore.projitems*{917b30de-f2c0-4955-b3b9-5bf90c3d01e9}*SharedItemsImports = 4 + NovetusCore\NovetusCore.projitems*{debcc57d-9a3b-4d7c-8693-fa4aec56c8c1}*SharedItemsImports = 13 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Release|Any CPU.Build.0 = Release|Any CPU + {78EE2921-681F-411A-90F2-773A5CE96B7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {78EE2921-681F-411A-90F2-773A5CE96B7E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {78EE2921-681F-411A-90F2-773A5CE96B7E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {78EE2921-681F-411A-90F2-773A5CE96B7E}.Release|Any CPU.Build.0 = Release|Any CPU + {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {66CA6CE5-670E-48AA-A2DA-9347371D4CA0} + EndGlobalSection +EndGlobal diff --git a/Novetus/Novetus.Tools.Net481.sln b/Novetus/Novetus.Tools.Net481.sln index b495e31..9de6280 100644 --- a/Novetus/Novetus.Tools.Net481.sln +++ b/Novetus/Novetus.Tools.Net481.sln @@ -1,31 +1,31 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32630.192 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Internal.ReleasePreparer", "G:\Projects\GitHub\Novetus\Novetus_src\Novetus\Novetus.ReleasePreparer\Novetus.Internal.ReleasePreparer.csproj", "{64A99062-3C1C-4D2E-99E4-D6D92443AC98}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.ClientScriptTester.Net481", "G:\Projects\GitHub\Novetus\Novetus_src\Novetus\Novetus.ClientScriptTester\Novetus.ClientScriptTester.Net481.csproj", "{83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Debug|Any CPU.Build.0 = Debug|Any CPU - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Release|Any CPU.ActiveCfg = Release|Any CPU - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Release|Any CPU.Build.0 = Release|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {66CA6CE5-670E-48AA-A2DA-9347371D4CA0} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32630.192 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Internal.ReleasePreparer", "Novetus.ReleasePreparer\Novetus.Internal.ReleasePreparer.csproj", "{64A99062-3C1C-4D2E-99E4-D6D92443AC98}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.ClientScriptTester.Net481", "Novetus.ClientScriptTester\Novetus.ClientScriptTester.Net481.csproj", "{83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Debug|Any CPU.Build.0 = Debug|Any CPU + {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Release|Any CPU.ActiveCfg = Release|Any CPU + {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Release|Any CPU.Build.0 = Release|Any CPU + {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {66CA6CE5-670E-48AA-A2DA-9347371D4CA0} + EndGlobalSection +EndGlobal -- 2.40.1 From ed105ec5c46a1a5c85b28e8401def859a5054cb3 Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 25 Nov 2022 15:45:55 -0700 Subject: [PATCH 02/85] fixed solution configuration --- Novetus/Novetus.Net481.sln | 12 ++++++------ Novetus/Novetus.Tools.Net481.sln | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Novetus/Novetus.Net481.sln b/Novetus/Novetus.Net481.sln index f0d9c9e..c570c9f 100644 --- a/Novetus/Novetus.Net481.sln +++ b/Novetus/Novetus.Net481.sln @@ -5,11 +5,11 @@ VisualStudioVersion = 17.2.32630.192 MinimumVisualStudioVersion = 10.0.40219.1 Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Novetus.Core", "NovetusCore\Novetus.Core.shproj", "{DEBCC57D-9A3B-4D7C-8693-FA4AEC56C8C1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Bootstrapper.Net481", "G:\Projects\GitHub\Novetus\Novetus_src\Novetus\Novetus.Bootstrapper\Novetus.Bootstrapper.Net481.csproj", "{8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Bootstrapper.Net481", "Novetus.Bootstrapper\Novetus.Bootstrapper.Net481.csproj", "{8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Launcher.Net481", "G:\Projects\GitHub\Novetus\Novetus_src\Novetus\NovetusLauncher\Novetus.Launcher.Net481.csproj", "{78EE2921-681F-411A-90F2-773A5CE96B7E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Launcher.Net481", "NovetusLauncher\Novetus.Launcher.Net481.csproj", "{78EE2921-681F-411A-90F2-773A5CE96B7E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.URI.Net481", "G:\Projects\GitHub\Novetus\Novetus_src\Novetus\NovetusURI\Novetus.URI.Net481.csproj", "{917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.URI.Net481", "NovetusURI\Novetus.URI.Net481.csproj", "{917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -37,9 +37,9 @@ Global SolutionGuid = {66CA6CE5-670E-48AA-A2DA-9347371D4CA0} EndGlobalSection GlobalSection(SharedMSBuildProjectFiles) = preSolution - G:\Projects\GitHub\Novetus\Novetus_src\Novetus\NovetusCore\NovetusCore.projitems*{78ee2921-681f-411a-90f2-773a5ce96b7e}*SharedItemsImports = 4 - G:\Projects\GitHub\Novetus\Novetus_src\Novetus\NovetusCore\NovetusCore.projitems*{8d030e72-bbf0-42e2-9dfb-c29e9e2a7e80}*SharedItemsImports = 4 - G:\Projects\GitHub\Novetus\Novetus_src\Novetus\NovetusCore\NovetusCore.projitems*{917b30de-f2c0-4955-b3b9-5bf90c3d01e9}*SharedItemsImports = 4 + NovetusCore\NovetusCore.projitems*{78ee2921-681f-411a-90f2-773a5ce96b7e}*SharedItemsImports = 4 + NovetusCore\NovetusCore.projitems*{8d030e72-bbf0-42e2-9dfb-c29e9e2a7e80}*SharedItemsImports = 4 + GNovetusCore\NovetusCore.projitems*{917b30de-f2c0-4955-b3b9-5bf90c3d01e9}*SharedItemsImports = 4 NovetusCore\NovetusCore.projitems*{debcc57d-9a3b-4d7c-8693-fa4aec56c8c1}*SharedItemsImports = 13 EndGlobalSection EndGlobal diff --git a/Novetus/Novetus.Tools.Net481.sln b/Novetus/Novetus.Tools.Net481.sln index b495e31..f0dd5b4 100644 --- a/Novetus/Novetus.Tools.Net481.sln +++ b/Novetus/Novetus.Tools.Net481.sln @@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.2.32630.192 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Internal.ReleasePreparer", "G:\Projects\GitHub\Novetus\Novetus_src\Novetus\Novetus.ReleasePreparer\Novetus.Internal.ReleasePreparer.csproj", "{64A99062-3C1C-4D2E-99E4-D6D92443AC98}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Internal.ReleasePreparer", "Novetus.ReleasePreparer\Novetus.Internal.ReleasePreparer.csproj", "{64A99062-3C1C-4D2E-99E4-D6D92443AC98}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.ClientScriptTester.Net481", "G:\Projects\GitHub\Novetus\Novetus_src\Novetus\Novetus.ClientScriptTester\Novetus.ClientScriptTester.Net481.csproj", "{83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.ClientScriptTester.Net481", "Novetus.ClientScriptTester\Novetus.ClientScriptTester.Net481.csproj", "{83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution -- 2.40.1 From 949138ca4b0efac7766a58fc3a1dd4a8344486b5 Mon Sep 17 00:00:00 2001 From: Bitl Date: Tue, 20 Dec 2022 07:17:42 -0700 Subject: [PATCH 03/85] prune old files. deprecate net 4.0 --- .../Novetus.Bootstrapper.Net481.csproj | 120 ----- .../Novetus.Bootstrapper.csproj | 13 +- .../Novetus.ClientScriptTester.Net481.csproj | 113 ----- .../Novetus.ClientScriptTester.csproj | 10 +- Novetus/Novetus.Net481.sln | 45 -- .../ReleasePreparer.cs | 123 +---- Novetus/Novetus.Tools.Net481.sln | 31 -- Novetus/Novetus.Tools.sln | 6 + Novetus/Novetus.sln | 48 +- .../Novetus.Launcher.Net481.csproj | 471 ------------------ .../NovetusLauncher/Novetus.Launcher.csproj | 71 +-- Novetus/NovetusURI/Novetus.URI.Net481.csproj | 223 --------- Novetus/NovetusURI/Novetus.URI.csproj | 61 ++- Novetus_SolutionLoader.bat | 43 -- README.md | 4 +- changelog.txt | 17 +- old/query.php | 83 --- .../Novetus_dependency_installer_4.0.bat | 104 ---- scripts/batch/create_lite.bat | 4 - scripts/batch/dev_menu.bat | 52 +- scripts/batch/github_sync.bat | 3 - scripts/batch/liteexclude.txt | 1 - scripts/batch/old/itch_loadNovetusCMDHelp.bat | 1 - scripts/batch/old/itch_loadNovetusSDK.bat | 3 - scripts/batch/old/itch_loadNovetusURI.bat | 27 - scripts/launcher/info.ini | 2 +- scripts/launcher/splashes.txt | 6 +- scripts/old/NovetusSetup.iss | 65 --- scripts/old/index.php | 13 - 29 files changed, 179 insertions(+), 1584 deletions(-) delete mode 100644 Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.Net481.csproj delete mode 100644 Novetus/Novetus.ClientScriptTester/Novetus.ClientScriptTester.Net481.csproj delete mode 100644 Novetus/Novetus.Net481.sln delete mode 100644 Novetus/Novetus.Tools.Net481.sln delete mode 100644 Novetus/NovetusLauncher/Novetus.Launcher.Net481.csproj delete mode 100644 Novetus/NovetusURI/Novetus.URI.Net481.csproj delete mode 100644 Novetus_SolutionLoader.bat delete mode 100644 old/query.php delete mode 100644 scripts/batch/Novetus_dependency_installer_4.0.bat delete mode 100644 scripts/batch/create_lite.bat delete mode 100644 scripts/batch/liteexclude.txt delete mode 100644 scripts/batch/old/itch_loadNovetusCMDHelp.bat delete mode 100644 scripts/batch/old/itch_loadNovetusSDK.bat delete mode 100644 scripts/batch/old/itch_loadNovetusURI.bat delete mode 100644 scripts/old/NovetusSetup.iss delete mode 100644 scripts/old/index.php diff --git a/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.Net481.csproj b/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.Net481.csproj deleted file mode 100644 index ccc557d..0000000 --- a/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.Net481.csproj +++ /dev/null @@ -1,120 +0,0 @@ - - - - - Debug - AnyCPU - {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80} - WinExe - Novetus.Bootstrapper - NovetusBootstrapper - v4.8 - 512 - false - - - - AnyCPU - true - full - false - bin\Debug\ - TRACE;DEBUG;BASICLAUNCHER;NOVETUS_APPS;NET481 - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE;BASICLAUNCHER;NOVETUS_APPS;NET481 - prompt - 4 - false - - - NovetusIcon.ico - - - app.manifest - - - - ..\packages\NLog.5.0.5\lib\net35\NLog.dll - - - - - - - - - - - - - - - - - - - - - - - Form - - - NovetusLaunchForm.cs - - - - - NovetusLaunchForm.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - SET path=$(SolutionDir)build -if not exist "%25path%25" mkdir "%25path%25" -copy $(ProjectDir)$(OutDir) "%25path%25"\* -del "%25path%25"\$(TargetName).vshost.exe -del "%25path%25"\$(TargetName).vshost.exe.config -del "%25path%25"\$(TargetName).vshost.exe.manifest -del "%25path%25"\$(TargetName).xml - - - - - - \ No newline at end of file diff --git a/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj b/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj index 95d5a23..ccc557d 100644 --- a/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj +++ b/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj @@ -4,13 +4,14 @@ Debug AnyCPU - {D7B467EE-A4B9-42FB-AA83-F487DA0F5CB1} + {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80} WinExe Novetus.Bootstrapper NovetusBootstrapper - v4.0 + v4.8 512 false + AnyCPU @@ -18,18 +19,20 @@ full false bin\Debug\ - TRACE;DEBUG;BASICLAUNCHER;NOVETUS_APPS;NET4 + TRACE;DEBUG;BASICLAUNCHER;NOVETUS_APPS;NET481 prompt 4 + false AnyCPU pdbonly true bin\Release\ - TRACE;BASICLAUNCHER;NOVETUS_APPS;NET4 + TRACE;BASICLAUNCHER;NOVETUS_APPS;NET481 prompt 4 + false NovetusIcon.ico @@ -45,6 +48,7 @@ + @@ -81,6 +85,7 @@ Resources.resx True + diff --git a/Novetus/Novetus.ClientScriptTester/Novetus.ClientScriptTester.Net481.csproj b/Novetus/Novetus.ClientScriptTester/Novetus.ClientScriptTester.Net481.csproj deleted file mode 100644 index bb378aa..0000000 --- a/Novetus/Novetus.ClientScriptTester/Novetus.ClientScriptTester.Net481.csproj +++ /dev/null @@ -1,113 +0,0 @@ - - - - - Debug - AnyCPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0} - WinExe - Novetus.ClientScriptTester - ClientScriptTester - v4.8 - 512 - - - - AnyCPU - true - full - false - bin\Debug\ - TRACE;DEBUG;TESTER;NOVETUS_APPS - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE;TESTER;NOVETUS_APPS;NET481 - prompt - 4 - false - - - NovetusIcon.ico - - - app.manifest - - - - - - - - - - - - - - - - - - - - - - Form - - - ClientScriptTestForm.cs - - - - - ClientScriptTestForm.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - SET path=$(SolutionDir)build -if not exist "%25path%25" mkdir "%25path%25" -SET path2=%25path%25\ClientScriptTester -if not exist "%25path2%25" mkdir "%25path2%25" -copy $(ProjectDir)$(OutDir) "%25path2%25"\* -del "%25path%25"\$(TargetName).vshost.exe -del "%25path%25"\$(TargetName).vshost.exe.config -del "%25path%25"\$(TargetName).vshost.exe.manifest -del "%25path%25"\$(TargetName).xml - - - - - - \ No newline at end of file diff --git a/Novetus/Novetus.ClientScriptTester/Novetus.ClientScriptTester.csproj b/Novetus/Novetus.ClientScriptTester/Novetus.ClientScriptTester.csproj index 43718c9..bb378aa 100644 --- a/Novetus/Novetus.ClientScriptTester/Novetus.ClientScriptTester.csproj +++ b/Novetus/Novetus.ClientScriptTester/Novetus.ClientScriptTester.csproj @@ -8,8 +8,9 @@ WinExe Novetus.ClientScriptTester ClientScriptTester - v4.0 + v4.8 512 + AnyCPU @@ -17,18 +18,20 @@ full false bin\Debug\ - TRACE;DEBUG;TESTER;NOVETUS_APPS;NET4 + TRACE;DEBUG;TESTER;NOVETUS_APPS prompt 4 + false AnyCPU pdbonly true bin\Release\ - TRACE;TESTER;NOVETUS_APPS;NET4 + TRACE;TESTER;NOVETUS_APPS;NET481 prompt 4 + false NovetusIcon.ico @@ -74,6 +77,7 @@ True Resources.resx + True diff --git a/Novetus/Novetus.Net481.sln b/Novetus/Novetus.Net481.sln deleted file mode 100644 index c570c9f..0000000 --- a/Novetus/Novetus.Net481.sln +++ /dev/null @@ -1,45 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32630.192 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Novetus.Core", "NovetusCore\Novetus.Core.shproj", "{DEBCC57D-9A3B-4D7C-8693-FA4AEC56C8C1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Bootstrapper.Net481", "Novetus.Bootstrapper\Novetus.Bootstrapper.Net481.csproj", "{8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Launcher.Net481", "NovetusLauncher\Novetus.Launcher.Net481.csproj", "{78EE2921-681F-411A-90F2-773A5CE96B7E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.URI.Net481", "NovetusURI\Novetus.URI.Net481.csproj", "{917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Release|Any CPU.Build.0 = Release|Any CPU - {78EE2921-681F-411A-90F2-773A5CE96B7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {78EE2921-681F-411A-90F2-773A5CE96B7E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {78EE2921-681F-411A-90F2-773A5CE96B7E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {78EE2921-681F-411A-90F2-773A5CE96B7E}.Release|Any CPU.Build.0 = Release|Any CPU - {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {66CA6CE5-670E-48AA-A2DA-9347371D4CA0} - EndGlobalSection - GlobalSection(SharedMSBuildProjectFiles) = preSolution - NovetusCore\NovetusCore.projitems*{78ee2921-681f-411a-90f2-773a5ce96b7e}*SharedItemsImports = 4 - NovetusCore\NovetusCore.projitems*{8d030e72-bbf0-42e2-9dfb-c29e9e2a7e80}*SharedItemsImports = 4 - GNovetusCore\NovetusCore.projitems*{917b30de-f2c0-4955-b3b9-5bf90c3d01e9}*SharedItemsImports = 4 - NovetusCore\NovetusCore.projitems*{debcc57d-9a3b-4d7c-8693-fa4aec56c8c1}*SharedItemsImports = 13 - EndGlobalSection -EndGlobal diff --git a/Novetus/Novetus.ReleasePreparer/ReleasePreparer.cs b/Novetus/Novetus.ReleasePreparer/ReleasePreparer.cs index 98a456d..3680341 100644 --- a/Novetus/Novetus.ReleasePreparer/ReleasePreparer.cs +++ b/Novetus/Novetus.ReleasePreparer/ReleasePreparer.cs @@ -14,89 +14,11 @@ namespace Novetus.ReleasePreparer { static void Main(string[] args) { + string novpath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\\Novetus"; + if (args.Length > 0) { - string novpath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\\Novetus"; - - if (args.Contains("-Net40")) - { - string litepath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\\Novetus-Net40"; - - if (!Directory.Exists(litepath)) - { - Console.WriteLine("Novetus Net 4.0 does not exist. Creating " + litepath); - Directory.CreateDirectory(litepath); - } - - List liteExcludeList = new List(); - - string liteExcludeFile = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\\Net40exclude.txt"; - Console.WriteLine("Reading exclusion list..."); - bool noExclusionList = false; - - if (File.Exists(liteExcludeFile)) - { - string[] liteExcludeArray = File.ReadAllLines(liteExcludeFile); - liteExcludeList.AddRange(liteExcludeArray); - } - else - { - noExclusionList = true; - } - - if (!noExclusionList) - { - //https://stackoverflow.com/questions/58744/copy-the-entire-contents-of-a-directory-in-c-sharp - - Console.WriteLine("Creating directories..."); - //Now Create all of the directories - foreach (string dirPath in Directory.GetDirectories(novpath, "*", SearchOption.AllDirectories)) - { - if (!liteExcludeList.Any(s => dirPath.Contains(s))) - { - Directory.CreateDirectory(dirPath.Replace(novpath, litepath)); - Console.WriteLine("D: " + dirPath.Replace(novpath, litepath)); - } - } - - Console.WriteLine("Copying files..."); - //Copy all the files & Replaces any files with the same name - foreach (string newPath in Directory.GetFiles(novpath, "*.*", SearchOption.AllDirectories)) - { - if (!liteExcludeList.Any(s => newPath.Contains(s))) - { - FixedFileCopy(newPath, newPath.Replace(novpath, litepath), true); - Console.WriteLine("F: " + newPath.Replace(novpath, litepath)); - } - } - - Console.WriteLine("Overwriting files with Net 4.0 alternatives..."); - string litefiles = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\\Net40files"; - - foreach (string newPath in Directory.GetFiles(litefiles, "*.*", SearchOption.AllDirectories)) - { - FixedFileCopy(newPath, newPath.Replace(litefiles, litepath), true); - Console.WriteLine("OW: " + newPath.Replace(litefiles, litepath)); - } - - string infopath = novpath + @"\\config\\info.ini"; - string currbranch = GetBranch(infopath); - TurnOnInitialSequence(infopath); - - string pathlite = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\\releasenomapsversion.txt"; - Console.WriteLine("Creating " + pathlite); - if (!File.Exists(pathlite)) - { - // Create a file to write to. - using (StreamWriter sw = File.CreateText(pathlite)) - { - sw.Write(currbranch); - } - } - Console.WriteLine("Created " + pathlite); - } - } - else if (args.Contains("-snapshot")) + if (args.Contains("-snapshot")) { string infopath = novpath + @"\\config\\info.ini"; string currver = GetBranch(infopath); @@ -116,23 +38,32 @@ namespace Novetus.ReleasePreparer } else if (args.Contains("-release")) { - string infopath = novpath + @"\\config\\info.ini"; - string currbranch = GetBranch(infopath); - TurnOnInitialSequence(infopath); - - string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\\releaseversion.txt"; - Console.WriteLine("Creating " + path); - if (!File.Exists(path)) - { - // Create a file to write to. - using (StreamWriter sw = File.CreateText(path)) - { - sw.Write(currbranch); - } - } - Console.WriteLine("Created " + path); + DoRelease(novpath); } } + else + { + DoRelease(novpath); + } + } + + public static void DoRelease(string novpath) + { + string infopath = novpath + @"\\config\\info.ini"; + string currbranch = GetBranch(infopath); + TurnOnInitialSequence(infopath); + + string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\\releaseversion.txt"; + Console.WriteLine("Creating " + path); + if (!File.Exists(path)) + { + // Create a file to write to. + using (StreamWriter sw = File.CreateText(path)) + { + sw.Write(currbranch); + } + } + Console.WriteLine("Created " + path); } public static void FixedFileCopy(string src, string dest, bool overwrite) diff --git a/Novetus/Novetus.Tools.Net481.sln b/Novetus/Novetus.Tools.Net481.sln deleted file mode 100644 index f0dd5b4..0000000 --- a/Novetus/Novetus.Tools.Net481.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32630.192 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Internal.ReleasePreparer", "Novetus.ReleasePreparer\Novetus.Internal.ReleasePreparer.csproj", "{64A99062-3C1C-4D2E-99E4-D6D92443AC98}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.ClientScriptTester.Net481", "Novetus.ClientScriptTester\Novetus.ClientScriptTester.Net481.csproj", "{83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Debug|Any CPU.Build.0 = Debug|Any CPU - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Release|Any CPU.ActiveCfg = Release|Any CPU - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Release|Any CPU.Build.0 = Release|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {66CA6CE5-670E-48AA-A2DA-9347371D4CA0} - EndGlobalSection -EndGlobal diff --git a/Novetus/Novetus.Tools.sln b/Novetus/Novetus.Tools.sln index b335a94..f90a1a5 100644 --- a/Novetus/Novetus.Tools.sln +++ b/Novetus/Novetus.Tools.sln @@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.2.32630.192 MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Internal.ReleasePreparer", "Novetus.ReleasePreparer\Novetus.Internal.ReleasePreparer.csproj", "{64A99062-3C1C-4D2E-99E4-D6D92443AC98}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.ClientScriptTester", "Novetus.ClientScriptTester\Novetus.ClientScriptTester.csproj", "{83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}" EndProject Global @@ -11,6 +13,10 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Debug|Any CPU.Build.0 = Debug|Any CPU + {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Release|Any CPU.ActiveCfg = Release|Any CPU + {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Release|Any CPU.Build.0 = Release|Any CPU {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Debug|Any CPU.Build.0 = Debug|Any CPU {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/Novetus/Novetus.sln b/Novetus/Novetus.sln index 20d3b35..06e002e 100644 --- a/Novetus/Novetus.sln +++ b/Novetus/Novetus.sln @@ -3,13 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.2.32630.192 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Launcher", "NovetusLauncher\Novetus.Launcher.csproj", "{F92FFBED-2767-4676-9711-BB89CDA58A43}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.URI", "NovetusURI\Novetus.URI.csproj", "{2070EAA6-7606-4006-A628-5705C24A3644}" -EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Novetus.Core", "NovetusCore\Novetus.Core.shproj", "{DEBCC57D-9A3B-4D7C-8693-FA4AEC56C8C1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Bootstrapper", "Novetus.Bootstrapper\Novetus.Bootstrapper.csproj", "{D7B467EE-A4B9-42FB-AA83-F487DA0F5CB1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Bootstrapper", "Novetus.Bootstrapper\Novetus.Bootstrapper.csproj", "{8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Launcher", "NovetusLauncher\Novetus.Launcher.csproj", "{78EE2921-681F-411A-90F2-773A5CE96B7E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.URI", "NovetusURI\Novetus.URI.csproj", "{917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,26 +17,18 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {F92FFBED-2767-4676-9711-BB89CDA58A43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F92FFBED-2767-4676-9711-BB89CDA58A43}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F92FFBED-2767-4676-9711-BB89CDA58A43}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F92FFBED-2767-4676-9711-BB89CDA58A43}.Release|Any CPU.Build.0 = Release|Any CPU - {2070EAA6-7606-4006-A628-5705C24A3644}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2070EAA6-7606-4006-A628-5705C24A3644}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2070EAA6-7606-4006-A628-5705C24A3644}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2070EAA6-7606-4006-A628-5705C24A3644}.Release|Any CPU.Build.0 = Release|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Release|Any CPU.Build.0 = Release|Any CPU - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Debug|Any CPU.Build.0 = Debug|Any CPU - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Release|Any CPU.ActiveCfg = Release|Any CPU - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Release|Any CPU.Build.0 = Release|Any CPU - {D7B467EE-A4B9-42FB-AA83-F487DA0F5CB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D7B467EE-A4B9-42FB-AA83-F487DA0F5CB1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D7B467EE-A4B9-42FB-AA83-F487DA0F5CB1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D7B467EE-A4B9-42FB-AA83-F487DA0F5CB1}.Release|Any CPU.Build.0 = Release|Any CPU + {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8D030E72-BBF0-42E2-9DFB-C29E9E2A7E80}.Release|Any CPU.Build.0 = Release|Any CPU + {78EE2921-681F-411A-90F2-773A5CE96B7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {78EE2921-681F-411A-90F2-773A5CE96B7E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {78EE2921-681F-411A-90F2-773A5CE96B7E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {78EE2921-681F-411A-90F2-773A5CE96B7E}.Release|Any CPU.Build.0 = Release|Any CPU + {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -45,9 +37,9 @@ Global SolutionGuid = {66CA6CE5-670E-48AA-A2DA-9347371D4CA0} EndGlobalSection GlobalSection(SharedMSBuildProjectFiles) = preSolution - NovetusCore\NovetusCore.projitems*{2070eaa6-7606-4006-a628-5705c24a3644}*SharedItemsImports = 4 - NovetusCore\NovetusCore.projitems*{d7b467ee-a4b9-42fb-aa83-f487da0f5cb1}*SharedItemsImports = 4 + NovetusCore\NovetusCore.projitems*{78ee2921-681f-411a-90f2-773a5ce96b7e}*SharedItemsImports = 4 + NovetusCore\NovetusCore.projitems*{8d030e72-bbf0-42e2-9dfb-c29e9e2a7e80}*SharedItemsImports = 4 + NovetusCore\NovetusCore.projitems*{917b30de-f2c0-4955-b3b9-5bf90c3d01e9}*SharedItemsImports = 4 NovetusCore\NovetusCore.projitems*{debcc57d-9a3b-4d7c-8693-fa4aec56c8c1}*SharedItemsImports = 13 - NovetusCore\NovetusCore.projitems*{f92ffbed-2767-4676-9711-bb89cda58a43}*SharedItemsImports = 4 EndGlobalSection EndGlobal diff --git a/Novetus/NovetusLauncher/Novetus.Launcher.Net481.csproj b/Novetus/NovetusLauncher/Novetus.Launcher.Net481.csproj deleted file mode 100644 index 7c04c47..0000000 --- a/Novetus/NovetusLauncher/Novetus.Launcher.Net481.csproj +++ /dev/null @@ -1,471 +0,0 @@ - - - - {78EE2921-681F-411A-90F2-773A5CE96B7E} - Debug - AnyCPU - WinExe - NovetusLauncher - Novetus - v4.8 - - - Properties - NovetusIcon.ico - False - False - False - obj\$(Configuration)\ - {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 4 - False - False - OnBuildSuccess - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - - - - x86 - 4194304 - False - Auto - 4096 - - - bin\Debug\ - True - Full - False - True - DEBUG;TRACE;LAUNCHER;NOVETUS_APPS;NET481 - obj\ - - - bin\Release\ - False - None - True - True - TRACE;LAUNCHER;NOVETUS_APPS;NET481 - obj\ - Project - - - false - x86 - TRACE;DEBUG;LAUNCHER;NOVETUS_APPS;NET481 - bin\Debug\ - - - false - x86 - pdbonly - true - TRACE;LAUNCHER;NOVETUS_APPS;NET481 - bin\Release\ - - - app.manifest - - - - - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Portable.BouncyCastle.1.8.8\lib\net40\BouncyCastle.Crypto.dll - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\BrotliSharpLib.0.3.3\lib\net451\BrotliSharpLib.dll - - - ..\packages\DotNetZip.1.16.0\lib\net40\DotNetZip.dll - - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll - - - ..\packages\Mono.Nat.1.2.24.0\lib\net40\Mono.Nat.dll - - - ..\packages\NLog.5.0.5\lib\net35\NLog.dll - - - - - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll - - - - 3.5 - - - - 3.5 - - - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll - - - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll - - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.AccessControl.5.0.0\lib\net461\System.Security.AccessControl.dll - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll - - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll - - - - - - - - 3.5 - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Titanium.Web.Proxy.3.1.1450\lib\net461\Titanium.Web.Proxy.dll - - - - - - - - - Forms\CharCustom\CharacterCustomizationShared.cs - - - Forms\CharCustom\Compact\CharacterCustomizationCompact.cs - Form - - - Forms\CharCustom\Compact\CharacterCustomizationCompact.designer.cs - CharacterCustomizationCompact.cs - - - Forms\CharCustom\Extended\CharacterCustomizationExtended.cs - Form - - - Forms\CharCustom\Extended\CharacterCustomizationExtended.designer.cs - CharacterCustomizationExtended.cs - - - - - - - Form - - - Decoder.cs - - - Form - - - CustomGraphicsOptions.cs - - - - Form - - - LauncherFormCompact.cs - - - Form - - - LauncherFormSettings.cs - - - Form - - - LauncherFormStylish.cs - - - LauncherFormStylishInterface.xaml - - - Form - - - NovetusConsole.cs - - - Form - - - ModCreator.cs - - - Form - - - AssetDownloader.cs - - - Form - - - AssetFixer.cs - - - Form - - - MeshConverter.cs - - - Form - - - ClientinfoCreator.cs - - - Form - - - ClientScriptDocumentation.cs - - - Form - - - ClientinfoCreatorValidatePathForm.cs - - - Form - - - DiogenesEditor.cs - - - Form - - - ItemCreationSDK.cs - - - Form - - - ItemCreationSDKColorMenu.cs - - - Form - - - NovetusSDK.cs - - - Form - - - SplashTester.cs - - - Form - - - XMLContentEditor.cs - - - Form - - - ServerBrowser.cs - - - True - True - Resources.resx - - - Form - - - LauncherFormExtended.cs - - - - - - - Forms\CharCustom\Compact\CharacterCustomizationCompact.resx - CharacterCustomizationCompact.cs - - - Forms\CharCustom\Extended\CharacterCustomizationExtended.resx - CharacterCustomizationExtended.cs - - - CustomGraphicsOptions.cs - - - Decoder.cs - - - LauncherFormCompact.cs - - - LauncherFormSettings.cs - - - LauncherFormExtended.cs - - - LauncherFormStylish.cs - - - NovetusConsole.cs - - - ModCreator.cs - - - AssetDownloader.cs - - - AssetFixer.cs - - - MeshConverter.cs - - - ClientinfoCreator.cs - - - ClientScriptDocumentation.cs - - - ClientinfoCreatorValidatePathForm.cs - - - DiogenesEditor.cs - - - ItemCreationSDK.cs - - - ItemCreationSDKColorMenu.cs - - - NovetusSDK.cs - - - SplashTester.cs - - - XMLContentEditor.cs - - - ServerBrowser.cs - - - PublicResXFileCodeGenerator - Resources.Designer.cs - - - - - - - - - - False - Microsoft .NET Framework 4 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 4.5 - true - - - - - - - - - - - - - - - - - - - - - - - - - - Designer - MSBuild:Compile - - - - - - SET path=$(SolutionDir)build -if not exist "%25path%25" mkdir "%25path%25" -SET path2=%25path%25\Launcher -if not exist "%25path2%25" mkdir "%25path2%25" -copy $(ProjectDir)$(OutDir) "%25path2%25"\* -del "%25path%25"\$(TargetName).vshost.exe -del "%25path%25"\$(TargetName).vshost.exe.config -del "%25path%25"\$(TargetName).vshost.exe.manifest -del "%25path%25"\$(TargetName).xml -if not exist "%25path%25"\bin mkdir "%25path%25"\bin -move "%25path2%25"\* "%25path%25"\bin -rd /s /q "%25path2%25" - - - - - - \ No newline at end of file diff --git a/Novetus/NovetusLauncher/Novetus.Launcher.csproj b/Novetus/NovetusLauncher/Novetus.Launcher.csproj index c44437a..7c04c47 100644 --- a/Novetus/NovetusLauncher/Novetus.Launcher.csproj +++ b/Novetus/NovetusLauncher/Novetus.Launcher.csproj @@ -1,13 +1,13 @@  - + - {F92FFBED-2767-4676-9711-BB89CDA58A43} + {78EE2921-681F-411A-90F2-773A5CE96B7E} Debug AnyCPU WinExe NovetusLauncher Novetus - v4.0 + v4.8 Properties @@ -52,7 +52,7 @@ Full False True - DEBUG;TRACE;LAUNCHER;NOVETUS_APPS;NET4 + DEBUG;TRACE;LAUNCHER;NOVETUS_APPS;NET481 obj\ @@ -61,20 +61,23 @@ None True True - TRACE;LAUNCHER;NOVETUS_APPS;NET4 + TRACE;LAUNCHER;NOVETUS_APPS;NET481 obj\ Project false x86 + TRACE;DEBUG;LAUNCHER;NOVETUS_APPS;NET481 + bin\Debug\ false x86 pdbonly true - TRACE;LAUNCHER;NOVETUS_APPS;NET4 + TRACE;LAUNCHER;NOVETUS_APPS;NET481 + bin\Release\ app.manifest @@ -83,21 +86,18 @@ + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Portable.BouncyCastle.1.8.8\lib\net40\BouncyCastle.Crypto.dll + + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\BrotliSharpLib.0.3.3\lib\net451\BrotliSharpLib.dll + ..\packages\DotNetZip.1.16.0\lib\net40\DotNetZip.dll - - ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll - True - - - ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll - True - - - ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll - True + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll ..\packages\Mono.Nat.1.2.24.0\lib\net40\Mono.Nat.dll @@ -109,6 +109,9 @@ + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + 3.5 @@ -118,18 +121,28 @@ 3.5 - - ..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.IO.dll - + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + - - ..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Runtime.dll + + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.AccessControl.5.0.0\lib\net461\System.Security.AccessControl.dll + + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll + - - ..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Threading.Tasks.dll + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll @@ -139,6 +152,9 @@ 3.5 + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Titanium.Web.Proxy.3.1.1450\lib\net461\Titanium.Web.Proxy.dll + @@ -448,13 +464,6 @@ if not exist "%25path%25"\bin mkdir "%25path%25"\bin move "%25path2%25"\* "%25path%25"\bin rd /s /q "%25path2%25" - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - diff --git a/Novetus/NovetusURI/Novetus.URI.Net481.csproj b/Novetus/NovetusURI/Novetus.URI.Net481.csproj deleted file mode 100644 index 3c38e3c..0000000 --- a/Novetus/NovetusURI/Novetus.URI.Net481.csproj +++ /dev/null @@ -1,223 +0,0 @@ - - - - - Debug - AnyCPU - {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9} - WinExe - Properties - NovetusURI - NovetusURI - v4.8 - 512 - true - - - - - - x86 - true - full - false - bin\Debug\ - TRACE;DEBUG;URI;NOVETUS_APPS;NET481 - none - 4 - 4096 - false - - - x86 - pdbonly - true - bin\Release\ - TRACE;URI;NOVETUS_APPS;NET481 - none - 4 - false - 4096 - true - - - NovetusIcon.ico - - - app.manifest - - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Portable.BouncyCastle.1.8.8\lib\net40\BouncyCastle.Crypto.dll - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\BrotliSharpLib.0.3.3\lib\net451\BrotliSharpLib.dll - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll - - - ..\packages\Mono.Nat.1.2.24.0\lib\net40\Mono.Nat.dll - - - ..\packages\NLog.5.0.5\lib\net35\NLog.dll - - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll - - - - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll - - - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll - - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.AccessControl.5.0.0\lib\net461\System.Security.AccessControl.dll - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll - - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll - - - - - - - - - - - - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Titanium.Web.Proxy.3.1.1450\lib\net461\Titanium.Web.Proxy.dll - - - - - Forms\CharCustom\CharacterCustomizationShared.cs - - - Forms\CharCustom\Compact\CharacterCustomizationCompact.cs - Form - - - Forms\CharCustom\Compact\CharacterCustomizationCompact.designer.cs - CharacterCustomizationCompact.cs - - - Forms\CharCustom\Extended\CharacterCustomizationExtended.cs - Form - - - Forms\CharCustom\Extended\CharacterCustomizationExtended.designer.cs - CharacterCustomizationExtended.cs - - - - - Form - - - InstallForm.cs - - - - - - Form - - - LoaderForm.cs - - - Form - - - QuickConfigure.cs - - - Forms\CharCustom\Compact\CharacterCustomizationCompact.resx - CharacterCustomizationCompact.cs - - - Forms\CharCustom\Extended\CharacterCustomizationExtended.resx - CharacterCustomizationExtended.cs - - - InstallForm.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - LoaderForm.cs - - - QuickConfigure.cs - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - - - SET path=$(SolutionDir)build -if not exist "%25path%25" mkdir "%25path%25" -SET path2=%25path%25\URI -if not exist "%25path2%25" mkdir "%25path2%25" -copy $(ProjectDir)$(OutDir) "%25path2%25"\* -del "%25path%25"\$(TargetName).vshost.exe -del "%25path%25"\$(TargetName).vshost.exe.config -del "%25path%25"\$(TargetName).vshost.exe.manifest -del "%25path%25"\$(TargetName).xml -if not exist "%25path%25"\bin mkdir "%25path%25"\bin -move "%25path2%25"\* "%25path%25"\bin -rd /s /q "%25path2%25" - - - - - - - \ No newline at end of file diff --git a/Novetus/NovetusURI/Novetus.URI.csproj b/Novetus/NovetusURI/Novetus.URI.csproj index 6d03684..3c38e3c 100644 --- a/Novetus/NovetusURI/Novetus.URI.csproj +++ b/Novetus/NovetusURI/Novetus.URI.csproj @@ -4,12 +4,12 @@ Debug AnyCPU - {2070EAA6-7606-4006-A628-5705C24A3644} + {917B30DE-F2C0-4955-B3B9-5BF90C3D01E9} WinExe Properties NovetusURI NovetusURI - v4.0 + v4.8 512 true @@ -22,17 +22,18 @@ full false bin\Debug\ - TRACE;DEBUG;URI;NOVETUS_APPS;NET4 + TRACE;DEBUG;URI;NOVETUS_APPS;NET481 none 4 4096 + false x86 pdbonly true bin\Release\ - TRACE;URI;NOVETUS_APPS;NET4 + TRACE;URI;NOVETUS_APPS;NET481 none 4 false @@ -46,17 +47,14 @@ app.manifest - - ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll - True + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Portable.BouncyCastle.1.8.8\lib\net40\BouncyCastle.Crypto.dll - - ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll - True + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\BrotliSharpLib.0.3.3\lib\net451\BrotliSharpLib.dll - - ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll - True + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll ..\packages\Mono.Nat.1.2.24.0\lib\net40\Mono.Nat.dll @@ -65,20 +63,33 @@ ..\packages\NLog.5.0.5\lib\net35\NLog.dll + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + - - ..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.IO.dll - + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + - - ..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Runtime.dll + + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.AccessControl.5.0.0\lib\net461\System.Security.AccessControl.dll + + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll + - - ..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Threading.Tasks.dll + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll @@ -90,6 +101,9 @@ + + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Titanium.Web.Proxy.3.1.1450\lib\net461\Titanium.Web.Proxy.dll + @@ -195,13 +209,6 @@ if not exist "%25path%25"\bin mkdir "%25path%25"\bin move "%25path2%25"\* "%25path%25"\bin rd /s /q "%25path2%25" - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - diff --git a/Novetus_SolutionLoader.bat b/Novetus_SolutionLoader.bat deleted file mode 100644 index c2f1763..0000000 --- a/Novetus_SolutionLoader.bat +++ /dev/null @@ -1,43 +0,0 @@ -@ECHO OFF -:CLEAN -CLS -echo Cleaning build directory -rd /s /q "%cd%\Novetus\build" - -echo Cleaning Novetus.Bootstrapper -rd /s /q "%cd%\Novetus\Novetus.Bootstrapper\bin" -rd /s /q "%cd%\Novetus\Novetus.Bootstrapper\obj" - -echo Cleaning Novetus.ClientScriptTester -rd /s /q "%cd%\Novetus\Novetus.ClientScriptTester\bin" -rd /s /q "%cd%\Novetus\Novetus.ClientScriptTester\obj" - -echo Cleaning Novetus.ReleasePreparer -rd /s /q "%cd%\Novetus\Novetus.ReleasePreparer\bin" -rd /s /q "%cd%\Novetus\Novetus.ReleasePreparer\obj" - -echo Cleaning NovetusLauncher -rd /s /q "%cd%\Novetus\NovetusLauncher\bin" -rd /s /q "%cd%\Novetus\NovetusLauncher\obj" - -echo Cleaning NovetusURI -rd /s /q "%cd%\Novetus\NovetusURI\bin" -rd /s /q "%cd%\Novetus\NovetusURI\obj" -goto MENU - -:MENU -CLS -ECHO Which solution do you wish to load? -ECHO. -ECHO 1 - Novetus (.NET Framework 4.0) -ECHO 2 - Novetus.Tools (.NET Framework 4.0) -ECHO 3 - Novetus (.NET Framework 4.8) -ECHO 4 - Novetus.Tools (.NET Framework 4.8) -ECHO 5 - EXIT -ECHO. -SET /P M=Option: -IF %M%==1 start "" "%cd%\Novetus\Novetus.sln" -IF %M%==2 start "" "%cd%\Novetus\Novetus.Tools.sln" -IF %M%==3 start "" "%cd%\Novetus\Novetus.Net481.sln" -IF %M%==4 start "" "%cd%\Novetus\Novetus.Tools.Net481.sln" -IF %M%==5 EXIT \ No newline at end of file diff --git a/README.md b/README.md index f5407b3..d5c71d1 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,7 @@ If you want to look at test applications built for Novetus' development, look he ## Building (Windows) To build, this project requires Visual Studio 2017 or over. Modern versions of Novetus are compiled with Visual Studio 2022. - -Open "Novetus_SolutionLoader.bat" and choose a solution. Then, right click the solution and click "Restore Nuget Packages" before compiling. -This batch file is used to clean and load solutions due to the move to .NET 6 conflicting with some files. +Open either "Novetus/Novetus.sln" or "Novetus/Novetus.Tools.sln". Then, right click the solution and click "Restore Nuget Packages" before compiling. ## Legal info: diff --git a/changelog.txt b/changelog.txt index 2f7e922..28b4352 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,18 @@ +1.3 Snapshot v22.8342.20628.1 +Enhancements: +Fixes: +- Fixed bullets arcing in Rise of the Killbots (credits to Ae1ouRed) +- Remastered audio in Rise of the Killbots to be less loud. +---------------------------------------------------------------------------- +1.3 Snapshot v22.8342.20628.1 +Enhancements: +- Added some of my original places from 2009-2011 as Novetus Exclusives! +- 2012M is now considered finished! + +Fixes: +- Fixed the UI in the Extended style on the .NET Framework 4.8 version. +- Fixed issues in 2010L-2012M where assetdelivery URLs didn't function reliably. +---------------------------------------------------------------------------- 1.3 Snapshot v22.8341.26380.2 Fixes: - Fixed 2011M not being able to load. @@ -263,7 +278,7 @@ Fixes: - Fixed 2010L server joining not working. - Fixed 2007E based clients not loading all customized parts properly. - Fixed master server pings making the launcher/CMD unresponsive. -- Rise of the Killbots: Fixed bullets not disappearing after a specified amount of time, causing soem optimization issues (https://itch.io/t/2277693/issues-with-bullets-in-rise-of-killbots) +- Rise of the Killbots: Fixed bullets not disappearing after a specified amount of time, causing some optimization issues (https://itch.io/t/2277693/issues-with-bullets-in-rise-of-killbots) ---------------------------------------------------------------------------- 1.3 Snapshot v22.8253.19867.1 Enhancements: diff --git a/old/query.php b/old/query.php deleted file mode 100644 index 6d9215d..0000000 --- a/old/query.php +++ /dev/null @@ -1,83 +0,0 @@ -. -*/ - -//NOVETUS MASTER SERVER QUERY CODE -//thanks to idkwhatnametoget for the port fix - -//name -$name = $_GET["name"]; -//port -$port = $_GET["port"]; -//client -$client = $_GET["client"]; -//version -$version = $_GET["version"]; - -if (!empty($port) and $port < 65535 and is_numeric($port) and !empty($name) and !empty($client) and !empty($version)) -{ - //server ip - $ip = $_GET["ip"]; - //online status - $online = $_GET["online"]; - - //strings - $deleteentry = 1; - $status = "Offline"; - - $file = 'serverlist.txt'; - - //ONLY the $name and $client arguments will show up in the master server! - $text = base64_encode(base64_encode($name).'|'.base64_encode($ip).'|'.base64_encode($port).'|'.base64_encode($client).'|'.base64_encode($version))."\r\n"; - - if ($online == 1) - { - $deleteentry = 0; - - foreach(file($file) as $line) - { - if (strpos($line, $text) !== false) - { - $file_contents = file_get_contents($file); - $contents = str_replace($line, '', $file_contents); - file_put_contents($file, $contents); - } - } - - file_put_contents($file, $text, FILE_APPEND); - - $status = "Online"; - } - - if ($deleteentry == 1) - { - foreach(file($file) as $line) - { - if (strpos($line, $text) !== false) - { - $file_contents = file_get_contents($file); - $contents = str_replace($line, '', $file_contents); - file_put_contents($file, $contents); - } - } - } - - // Display the server info to browsers. - echo "" . htmlspecialchars($name) . ". A " . htmlspecialchars($client) . " server running on ". htmlspecialchars($version) .". Server Status: " . htmlspecialchars($status) . ""; -} -?> \ No newline at end of file diff --git a/scripts/batch/Novetus_dependency_installer_4.0.bat b/scripts/batch/Novetus_dependency_installer_4.0.bat deleted file mode 100644 index fcac863..0000000 --- a/scripts/batch/Novetus_dependency_installer_4.0.bat +++ /dev/null @@ -1,104 +0,0 @@ -@ECHO OFF -setlocal -cd /d %~dp0 -:REDISTINSTALLER -TITLE NOVETUS DEPENDENCY INSTALLER -ECHO --------------------------------------------------------------------------- -ECHO NhhhhhhhhhhN hsssoosssd -ECHO NyyyyhhhhyyhdN hoo++++++h -ECHO NyyyyyhhhhyyyhN hoo+++///h -ECHO NssssyyyyyhyyyhdN hoo+++///h -ECHO Nsossssyyyyyyyyyhm hsoo++///h -ECHO NsssssssssyyyyyyyhdN hssoo++//h -ECHO Nsssssssssssyyyyhhhdm hsssoo+++h -ECHO NyssssssssysyyyyhhhhhdN NNNNNmmmmdddddhhysoooo+++ymNN -ECHO Nhyyssssssmdyyyyhhhhhyhyysssssooooooooosssooooo++osssyhdmN -ECHO Nhyyyyssssddhyyyhhyyysssosyyhhhddmmmmmmmyooooo+++yhyssoosydN -ECHO NdhhyyyysssoosyhyyyssooooydN y++++++++hN NNdhsoohN -ECHO NmdhhhyyyysyhddmNmhyssooooooshN s++++++++h doosm -ECHO NNdhysoyyyysssssm NdsoooooooooydN s/////+++h NmyooyN -ECHO Ndysoosyhyysssooosm myooooooososhN s///////+h Ndhsoshm -ECHO mhsoosydmNmysooooooom NdssssssssooydN s////////hdhssosydN -ECHO NhsosydN Nsoooo+++om mhssssssoooohm y++/////+soosyhmN -ECHO NhoosdN Nsooo+++oom NdyssssooooosdN Ny++++oooosydmN -ECHO msood Noooooooosm Nhssooooooooydhysoooo++++hN -ECHO NhooshmN Nsoooooossm Nmhsoooooooooooso++////++h -ECHO Nhysossyhhdddoooooooosdmmmmmdddhhhyysssoooooooooo++ss++//++++h -ECHO Nmhyyssooooooooooooosssooooooossssyyhhdds+++++++++++++++oood -ECHO NNmmmddssooooooohhhhddddmmmNNNN Ny+++++++++++++osssd -ECHO Nyyssssoosm Nds+++++++++oosssyd -ECHO Nhyyysssssm Nho++++++oossssyd -ECHO Nyyyyyssssm ms+++++ooossssd -ECHO Nyyyssssssm Nho+++ooossssd -ECHO Nhyyyyyyyym mysssssyyyyd -ECHO --------------------------------------------------------------------------- -ECHO. -ECHO NOVETUS DEPENDENCY INSTALLER -ECHO. -ECHO Please install the following if you haven't already: -ECHO 1 - Microsoft .NET Framework 2.0 (REQUIRED for the ROBLOX Script Generator SDK tool) -ECHO 2 - Microsoft .NET Framework 4.0 (REQUIRED for the Novetus Launcher) -ECHO 3 - .NET 4.0 Update (KB2468871, REQUIRED for Windows XP and Vista) -ECHO 4 - Microsoft Visual C++ Redistributables 2005 (32-bit, REQUIRED for 2007) -ECHO 5 - Microsoft Visual C++ Redistributables 2008 (32-bit, REQUIRED for 2008 and above) -ECHO 6 - Windows Media Player (REQUIRED for 2010L+) -ECHO 7 - Exit -ECHO. -SET /P M=Choose an option by typing the number corresponding to which depenency you want to install: -IF %M%==1 goto net2 -IF %M%==2 goto net4 -IF %M%==3 goto net4update -IF %M%==4 goto vc2005 -IF %M%==5 goto vc2008 -IF %M%==6 goto mfp -IF %M%==7 EXIT -EXIT - -:net2 -CLS -echo Installing Microsoft .NET Framework 2.0... -reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && set OS=32BIT || set OS=64BIT - -if %OS%==32BIT "%CD%/_redist/NET Framework/NetFx20SP2_x86.exe" -if %OS%==64BIT "%CD%/_redist/NET Framework/NetFx20SP2_x64.exe" -pause -goto REDISTINSTALLER - -:net4 -CLS -echo Installing Microsoft .NET Framework 4.0... -"%CD%/_redist/NET Framework/dotNetFx40_Full_x86_x64.exe" -pause -goto REDISTINSTALLER - -:net4update -CLS -echo Installing .NET 4.0 Update (KB2468871)... -reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && set OS=32BIT || set OS=64BIT - -if %OS%==32BIT "%CD%/_redist/NET Framework/NDP40-KB2468871-v2-x86 (XP and Vista Only).exe" -if %OS%==64BIT "%CD%/_redist/NET Framework/NDP40-KB2468871-v2-x64 (XP and Vista Only).exe" -pause -goto REDISTINSTALLER - -:vc2005 -CLS -echo Installing Microsoft Visual C++ Redistributables 2005 (32-bit)... -"%CD%/_redist/Visual C++ Redistributables/vcredist2005_x86.exe" -pause -goto REDISTINSTALLER - -:vc2008 -CLS -echo Installing Microsoft Visual C++ Redistributables 2008 (32-bit)... -"%CD%/_redist/Visual C++ Redistributables/vcredist2008_x86.exe" -pause -goto REDISTINSTALLER - -:mfp -CLS -echo Please install the Windows Media Player through Windows' "Add a feature" utility. -echo Windows 7+: Go to the Control Panel, Programs and Features, go to "Turn Windows features on and off", and enable Windows Media Player in Media Features. -echo Windows 10+: Go to the Settings app, Apps, Optional Features, then search "Windows Media Player", then select it and press Install. -pause -goto REDISTINSTALLER \ No newline at end of file diff --git a/scripts/batch/create_lite.bat b/scripts/batch/create_lite.bat deleted file mode 100644 index 74c4c7f..0000000 --- a/scripts/batch/create_lite.bat +++ /dev/null @@ -1,4 +0,0 @@ -@ECHO OFF -call clean_junk.bat -ReleasePreparer.exe -Net40 -pause \ No newline at end of file diff --git a/scripts/batch/dev_menu.bat b/scripts/batch/dev_menu.bat index 2efa90d..1800575 100644 --- a/scripts/batch/dev_menu.bat +++ b/scripts/batch/dev_menu.bat @@ -8,25 +8,22 @@ ECHO ----------------------------------------------- ECHO Novetus Release Utility ECHO ----------------------------------------------- ECHO. -ECHO 1 - Release (4.8) +ECHO 1 - Release ECHO 2 - Release Beta -ECHO 3 - Release (4.0) -ECHO 4 - Validate manifest -ECHO 5 - itch.io build status. -ECHO 6 - Push File List. -ECHO 7 - EXIT +ECHO 3 - Validate manifest +ECHO 4 - itch.io build status. +ECHO 5 - Push File List. +ECHO 6 - EXIT ECHO. SET /P M=Option: IF %M%==1 SET releaseoption=1 IF %M%==1 GOTO CLEANUP IF %M%==2 SET releaseoption=2 IF %M%==2 GOTO CLEANUP -IF %M%==3 SET releaseoption=3 -IF %M%==3 GOTO CLEANUP -IF %M%==4 GOTO VALIDATE -IF %M%==5 GOTO STATUS -IF %M%==6 GOTO PUSHFILELISTMENU -IF %M%==7 EXIT +IF %M%==3 GOTO VALIDATE +IF %M%==4 GOTO STATUS +IF %M%==5 GOTO PUSHFILELISTMENU +IF %M%==6 EXIT :PUSHFILELISTMENU CLS @@ -34,19 +31,16 @@ ECHO ----------------------------------------------- ECHO Push File List for: ECHO ----------------------------------------------- ECHO. -ECHO 1 - Release (4.8) +ECHO 1 - Release ECHO 2 - Release Beta -ECHO 3 - Release (4.0) -ECHO 4 - Back +ECHO 3 - Back ECHO. SET /P M=Option: IF %M%==1 SET checkoption=1 IF %M%==1 GOTO CLEANUP_DRY IF %M%==2 SET checkoption=2 IF %M%==2 GOTO CLEANUP_DRY -IF %M%==3 SET checkoption=3 -IF %M%==3 GOTO CLEANUP_DRY -IF %M%==4 GOTO MENU +IF %M%==3 GOTO MENU :CLEANJUNK call clean_junk.bat @@ -63,11 +57,9 @@ GOTO CLEANJUNK :POSTCLEANUP IF %releaseoption%==1 echo Press any key to push Release build IF %releaseoption%==2 echo Press any key to push Beta build -IF %releaseoption%==3 echo Press any key to push Release Lite build pause IF %releaseoption%==1 GOTO RELEASE IF %releaseoption%==2 GOTO BETA -IF %releaseoption%==3 GOTO RELEASENOMAPS :CLEANUP_DRY CLS @@ -77,10 +69,8 @@ GOTO CLEANJUNK :POSTCLEANUP_DRY IF %checkoption%==1 echo Press any key to check Release build IF %checkoption%==2 echo Press any key to check Beta build -IF %checkoption%==3 echo Press any key to check Release Lite build IF %checkoption%==1 GOTO RELEASE_DRY IF %checkoption%==2 GOTO BETA_DRY -IF %checkoption%==3 GOTO RELEASENOMAPS_DRY :RELEASE CLS @@ -89,13 +79,6 @@ butler push Novetus bitl/novetus:windows --if-changed --userversion-file release pause GOTO MENU -:RELEASENOMAPS -CLS -ReleasePreparer.exe -Net40 -butler push Novetus-Lite bitl/novetus:windows-lite --if-changed --userversion-file releasenomapsversion.txt -pause -GOTO MENU - :BETA CLS ReleasePreparer.exe -snapshot @@ -110,13 +93,6 @@ butler push Novetus bitl/novetus:windows --if-changed --userversion-file release pause GOTO MENU -:RELEASENOMAPS_DRY -CLS -ReleasePreparer.exe -Net40 -butler push Novetus-Lite bitl/novetus:windows-lite --if-changed --userversion-file releasenomapsversion.txt --dry-run -pause -GOTO MENU - :BETA_DRY CLS ReleasePreparer.exe -snapshot @@ -132,10 +108,8 @@ GOTO MENU :STATUS CLS -echo RELEASE NET48 +echo RELEASE butler status bitl/novetus:windows -echo RELEASE NET40 -butler status bitl/novetus:windows-lite echo BETA butler status bitl/novetus:windows-beta pause diff --git a/scripts/batch/github_sync.bat b/scripts/batch/github_sync.bat index 231e36f..0004d34 100644 --- a/scripts/batch/github_sync.bat +++ b/scripts/batch/github_sync.bat @@ -144,11 +144,8 @@ if not exist "%dest%\scripts\batch" mkdir "%scriptsdir%\batch" XCOPY "%cd%\dev_menu.bat" "%scriptsdir%\batch" /y XCOPY "%cd%\clean_junk.bat" "%scriptsdir%\batch" /y XCOPY "%cd%\github_sync.bat" "%scriptsdir%\batch" /y -XCOPY "%cd%\create_lite.bat" "%scriptsdir%\batch" /y -XCOPY "%cd%\liteexclude.txt" "%scriptsdir%\batch" /y XCOPY "%cd%\assetfixer_gauntlet.lua" "%scriptsdir%" /y XCOPY "%cd%\Novetus\Novetus_dependency_installer.bat" "%scriptsdir%\batch" /y -XCOPY "%cd%\Net40files\Novetus_dependency_installer.bat" "%scriptsdir%\batch\Novetus_dependency_installer_4.0.bat*" /y XCOPY "%cd%\Novetus\Novetus_launcher_legacy.bat" "%scriptsdir%\batch" /y XCOPY "%cd%\Novetus\documentation.txt" "%dest%" /y XCOPY "%cd%\Novetus\consolehelp.txt" "%dest%" /y diff --git a/scripts/batch/liteexclude.txt b/scripts/batch/liteexclude.txt deleted file mode 100644 index b0c2e2c..0000000 --- a/scripts/batch/liteexclude.txt +++ /dev/null @@ -1 +0,0 @@ -ndp48-x86-x64-allos-enu.exe \ No newline at end of file diff --git a/scripts/batch/old/itch_loadNovetusCMDHelp.bat b/scripts/batch/old/itch_loadNovetusCMDHelp.bat deleted file mode 100644 index 980d276..0000000 --- a/scripts/batch/old/itch_loadNovetusCMDHelp.bat +++ /dev/null @@ -1 +0,0 @@ -"bin/NovetusCMD.exe" -help \ No newline at end of file diff --git a/scripts/batch/old/itch_loadNovetusSDK.bat b/scripts/batch/old/itch_loadNovetusSDK.bat deleted file mode 100644 index ec7cc05..0000000 --- a/scripts/batch/old/itch_loadNovetusSDK.bat +++ /dev/null @@ -1,3 +0,0 @@ -@ECHO OFF -start "" "%CD%/bin/Novetus.exe" -sdk -EXIT \ No newline at end of file diff --git a/scripts/batch/old/itch_loadNovetusURI.bat b/scripts/batch/old/itch_loadNovetusURI.bat deleted file mode 100644 index eb15740..0000000 --- a/scripts/batch/old/itch_loadNovetusURI.bat +++ /dev/null @@ -1,27 +0,0 @@ -@ECHO OFF -REM --> https://superuser.com/questions/705813/batch-file-with-commands-to-run-as-administrator-and-standard-user -:: BatchGotAdmin -:------------------------------------- -REM --> Check for permissions ->nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" - -REM --> If error flag set, we do not have admin. -if '%errorlevel%' NEQ '0' ( - echo Requesting administrative privileges... - goto UACPrompt -) else ( goto gotAdmin ) - -:UACPrompt - echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" - echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs" - - "%temp%\getadmin.vbs" - exit /B - -:gotAdmin - if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" ) - pushd "%CD%" - CD /D "%~dp0" - -start "" "%CD%/bin/NovetusURI.exe" -EXIT \ No newline at end of file diff --git a/scripts/launcher/info.ini b/scripts/launcher/info.ini index 038d3c0..ff02e34 100644 --- a/scripts/launcher/info.ini +++ b/scripts/launcher/info.ini @@ -8,6 +8,6 @@ ExtendedVersionNumber=True ExtendedVersionEditChangelog=True //ExtendedVersionTemplate=%version% v11.2022.%extended-revision%%lite% ExtendedVersionTemplate=%version% Snapshot v22.%build%.%revision%.%extended-revision% -ExtendedVersionRevision=2 +ExtendedVersionRevision=1 InitialBootup=False IsLite=False diff --git a/scripts/launcher/splashes.txt b/scripts/launcher/splashes.txt index 2a9de16..9705de1 100644 --- a/scripts/launcher/splashes.txt +++ b/scripts/launcher/splashes.txt @@ -239,4 +239,8 @@ Don't fence me in! Pick it Up!|Ima Say Ma Namowa Put it Down!|Ima Say Ma Namowa Down with Monogon! -allows the user to use W... \ No newline at end of file +allows the user to use W... +[stylish]I DROPPED MY PHONE IN MCDONALD'S SPRITE...|...AND THAT MOTHERFUCKER STARTED CHARGING!! +[normal]I'm the Toa of... of... Anarchy. +[stylish]My name is... ah... Toa Vezon. I'm the Toa of... of... Anarchy. +Your System ate a SPARC! Gah! \ No newline at end of file diff --git a/scripts/old/NovetusSetup.iss b/scripts/old/NovetusSetup.iss deleted file mode 100644 index 22deab7..0000000 --- a/scripts/old/NovetusSetup.iss +++ /dev/null @@ -1,65 +0,0 @@ -; Script generated by the Inno Script Studio Wizard. -; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! - -#define AppVer "1.0.0" - -[Setup] -; NOTE: The value of AppId uniquely identifies this application. -; Do not use the same AppId value in installers for other applications. -; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) -AppId={{AC107FB8-A904-4D2C-8E4D-049808EB136E} -AppName=Novetus {#AppVer} -AppVersion={#AppVer} -AppVerName=Novetus {#AppVer} -AppPublisher=Bitl -DefaultDirName=C:\Novetus\{#AppVer} -DefaultGroupName=Novetus\{#AppVer} -AllowNoIcons=yes -OutputDir=. -OutputBaseFilename=NovetusSetup_{#AppVer} -SetupIconFile=Novetus\NovetusIcon.ico -Compression=lzma2/ultra64 -SolidCompression=yes - -[Languages] -Name: "english"; MessagesFile: "compiler:Default.isl" - -[Tasks] -Name: "desktopicon"; Description: "Create a icon on your Desktop"; GroupDescription: "Icons" -Name: "quicklaunchicon"; Description: "Create a icon on your Quick Launch Menu"; GroupDescription: "Icons"; Flags: unchecked; OnlyBelowVersion: 0,6.1 - -[Files] -Source: "Novetus\Novetus.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "Novetus\Novetus.exe.config"; DestDir: "{app}"; Flags: ignoreversion -Source: "Novetus\NovetusCMD.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "Novetus\NovetusCMD.exe.config"; DestDir: "{app}"; Flags: ignoreversion -Source: "Novetus\NovetusSDK.bat"; DestDir: "{app}"; Flags: ignoreversion -Source: "Novetus\discord-rpc.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "Novetus\Mono.Nat.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "Novetus\README.TXT"; DestDir: "{app}"; Flags: ignoreversion -Source: "Novetus\changelog.txt"; DestDir: "{app}"; Flags: ignoreversion -Source: "Novetus\documentation.txt"; DestDir: "{app}"; Flags: ignoreversion -Source: "Novetus\LICENCE.txt"; DestDir: "{app}"; Flags: ignoreversion -Source: "Novetus\novetus_steamartwork.png"; DestDir: "{app}"; Flags: ignoreversion -Source: "Novetus\clients\*"; DestDir: "{app}\clients"; Flags: ignoreversion recursesubdirs createallsubdirs -Source: "Novetus\maps\*"; DestDir: "{app}\maps"; Flags: ignoreversion recursesubdirs createallsubdirs -Source: "Novetus\models\*"; DestDir: "{app}\models"; Flags: ignoreversion recursesubdirs createallsubdirs -Source: "Novetus\config\*"; DestDir: "{app}\config"; Flags: ignoreversion recursesubdirs createallsubdirs -Source: "Novetus\shareddata\*"; DestDir: "{app}\shareddata"; Flags: ignoreversion recursesubdirs createallsubdirs -Source: "Novetus\_redist\*"; DestDir: "{app}\_redist"; Flags: ignoreversion recursesubdirs createallsubdirs - -[Icons] -Name: "{group}\Novetus {#AppVer}"; Filename: "{app}\Novetus.exe" -Name: "{group}\Utilities\Novetus SDK"; Filename: "{app}\Novetus.exe"; Parameters: "-sdk" -Name: "{group}\Uninstall Novetus {#AppVer}"; Filename: "{uninstallexe}" -Name: "{commondesktop}\Novetus {#AppVer}"; Filename: "{app}\Novetus.exe"; Tasks: desktopicon -Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\Novetus {#AppVer}"; Filename: "{app}\Novetus.exe"; Tasks: quicklaunchicon - -[Run] -Filename: "{app}\_redist\dotnetfx45_full_x86_x64.exe"; Description: "Install Microsoft .NET Framework 4.5"; Flags: nowait postinstall skipifsilent -Filename: "{app}\_redist\vcredist2005_x86.exe"; Description: "Install Microsoft Visual C++ 2005 Redistributable (32-bit)"; Flags: nowait postinstall skipifsilent -Filename: "{app}\_redist\vcredist2008_x86.exe"; Description: "Install Microsoft Visual C++ 2008 Redistributable (32-bit)"; Flags: nowait postinstall skipifsilent -Filename: "{app}\Novetus.exe"; Description: "Play Novetus"; Flags: nowait postinstall skipifsilent unchecked -Filename: "{app}\Novetus.exe"; Description: "Open the Novetus SDK"; Parameters: "-sdk"; Flags: nowait postinstall skipifsilent unchecked -Filename: "{app}\README.TXT"; Description: "View the README file"; Flags: postinstall shellexec skipifsilent unchecked -Filename: "{app}\changelog.txt"; Description: "View the changelog"; Flags: postinstall shellexec skipifsilent unchecked \ No newline at end of file diff --git a/scripts/old/index.php b/scripts/old/index.php deleted file mode 100644 index 63ee993..0000000 --- a/scripts/old/index.php +++ /dev/null @@ -1,13 +0,0 @@ - -Novetus Webserver Test Page - -
FUCKING HORSES!!!!!!!!
- - - - - \ No newline at end of file -- 2.40.1 From e3956d12ecaa019b39c53f0da18c7072cf9bc7e8 Mon Sep 17 00:00:00 2001 From: Bitl Date: Tue, 20 Dec 2022 09:18:26 -0700 Subject: [PATCH 04/85] changes galore! --- .itch.toml | 43 ++++++++--- .../Novetus.Bootstrapper.csproj | 3 +- Novetus/Novetus.Bootstrapper/packages.config | 2 +- Novetus/NovetusCore/Classes/Downloader.cs | 23 +++--- .../StorageAndFunctions/ClientManagement.cs | 2 +- .../StorageAndFunctions/NetFuncs.cs | 3 - .../StorageAndFunctions/NovetusFuncs.cs | 22 +----- .../NovetusLauncher/Forms/NovetusConsole.cs | 8 +- .../NovetusLauncher/Forms/SDK/AssetFixer.cs | 21 ++++- .../NovetusLauncher/Novetus.Launcher.csproj | 27 +++---- Novetus/NovetusLauncher/app.config | 26 +++++-- Novetus/NovetusLauncher/packages.config | 17 ++-- Novetus/NovetusURI/App.config | 12 +++ Novetus/NovetusURI/Novetus.URI.csproj | 27 +++---- Novetus/NovetusURI/packages.config | 17 ++-- changelog.txt | 11 +++ consolehelp.txt | 2 +- scripts/batch/Novetus_launcher_admin.bat | 26 ------- scripts/batch/Novetus_launcher_legacy.bat | 77 ------------------- scripts/batch/github_sync.bat | 1 - 20 files changed, 158 insertions(+), 212 deletions(-) delete mode 100644 scripts/batch/Novetus_launcher_admin.bat delete mode 100644 scripts/batch/Novetus_launcher_legacy.bat diff --git a/.itch.toml b/.itch.toml index 642ca4f..453f009 100644 --- a/.itch.toml +++ b/.itch.toml @@ -1,16 +1,35 @@ [[actions]] -name = "Play" -path = "NovetusBootstrapper.exe" -sandbox = true - -[[actions]] -name = "Play (Legacy Launcher. USE THIS IF YOU DON'T HAVE NET FRAMEWORK 4.0 INSTALLED.)" -path = "Novetus_launcher_legacy.bat" -console = true -sandbox = true - -[[actions]] -name = "Install Dependencies" +name = "[IMPORTANT] Install Dependencies" path = "Novetus_dependency_installer.bat" console = true +sandbox = true + +[[actions]] +name = "Play" +path = "bin/Novetus.exe" +args = ["-nocmd"] +sandbox = true + +[[actions]] +name = "Play with Console" +path = "bin/Novetus.exe" +args = ["-nocmd"] +sandbox = true + +[[actions]] +name = "Novetus SDK" +path = "bin/Novetus.exe" +args = ["-sdk"] +sandbox = true + +[[actions]] +name = "Novetus Console" +path = "bin/Novetus.exe" +args = ["-cmdonly", "-cmdmode"] +sandbox = true + +[[actions]] +name = "Novetus Console Help" +path = "bin/Novetus.exe" +args = ["-cmdonly", "-help"] sandbox = true \ No newline at end of file diff --git a/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj b/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj index ccc557d..b41674f 100644 --- a/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj +++ b/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj @@ -42,11 +42,12 @@
- ..\packages\NLog.5.0.5\lib\net35\NLog.dll + ..\packages\NLog.5.1.0\lib\net46\NLog.dll + diff --git a/Novetus/Novetus.Bootstrapper/packages.config b/Novetus/Novetus.Bootstrapper/packages.config index 7a37563..5a7cee2 100644 --- a/Novetus/Novetus.Bootstrapper/packages.config +++ b/Novetus/Novetus.Bootstrapper/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/Novetus/NovetusCore/Classes/Downloader.cs b/Novetus/NovetusCore/Classes/Downloader.cs index 8cc473b..c9f9b44 100644 --- a/Novetus/NovetusCore/Classes/Downloader.cs +++ b/Novetus/NovetusCore/Classes/Downloader.cs @@ -14,7 +14,8 @@ class Downloader public readonly string fileName; public readonly string fileFilter; public readonly string filePath; - public static bool showErrorInfo; + public static bool showErrorInfo = true; + public static bool overwrite = true; public int downloadSize; private string downloadOutcome; private static string downloadOutcomeException; @@ -41,9 +42,10 @@ class Downloader fileFilter = ""; } - public void setDownloadOutcome(string text) + public void setDownloadOptions(bool ExtraErrorInfo, bool OverwriteFiles) { - downloadOutcome = text; + showErrorInfo = ExtraErrorInfo; + overwrite = OverwriteFiles; } public string getDownloadOutcome() @@ -51,15 +53,8 @@ class Downloader return downloadOutcome; } - public void InitDownload(string path, string fileext, string additionalText = "") + public void InitDownloadDirect(string path, string fileext, string additionalText = "", bool removeSpaces = false) { - InitDownload(path, fileext, additionalText); - } - - public void InitDownload(string path, string fileext, string additionalText, bool removeSpaces = false, bool extraErrorInfo = true) - { - showErrorInfo = extraErrorInfo; - string outputfilename = ""; if (removeSpaces == true) @@ -94,6 +89,12 @@ class Downloader public void InitDownloadNoDialog(string name, string additionalText = "") { + if (!overwrite && File.Exists(name)) + { + downloadOutcome = "Download skipped due to same file name."; + return; + } + int read = 0; try diff --git a/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs b/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs index 1be268f..5e33925 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs @@ -1270,7 +1270,7 @@ public class ClientManagement case ScriptType.Studio: break; case ScriptType.Server: - NovetusFuncs.PingMasterServer(true, "Server will now display on the defined master server."); + NovetusFuncs.PingMasterServer(true, "Server will now display on the defined master server, if available."); goto default; default: GlobalVars.GameOpened = type; diff --git a/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs b/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs index 7f962af..dfd2057 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs @@ -13,7 +13,6 @@ public static class NetFuncs if (GlobalVars.UserConfiguration.UPnP) { NatUtility.DeviceFound += DeviceFound; - NatUtility.DeviceLost += DeviceLost; NatUtility.StartDiscovery(); } } @@ -29,7 +28,6 @@ public static class NetFuncs if (mapPublic == -1 && mapPrivate == -1) { Mapping portmap = new Mapping(protocol, port, port); - portmap.Description = "Novetus"; device.CreatePortMap(portmap); } } @@ -46,7 +44,6 @@ public static class NetFuncs if (mapPublic != -1 && mapPrivate != -1) { Mapping portmap = new Mapping(protocol, port, port); - portmap.Description = "Novetus"; device.DeletePortMap(portmap); } } diff --git a/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs b/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs index 8de25e8..0a5840e 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs @@ -169,7 +169,7 @@ public class NovetusFuncs if (!GlobalVars.ServerID.Equals("N/A")) { - Util.ConsolePrint("Your server's ID is " + GlobalVars.ServerID, 4); + Util.ConsolePrint("Master server ping successful. Your server's ID is " + GlobalVars.ServerID, 4); } GlobalVars.PingURL = ""; @@ -192,7 +192,7 @@ public class NovetusFuncs GameServer server = new GameServer((!string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : GlobalVars.ExternalIP), GlobalVars.UserConfiguration.RobloxPort); string[] text = { - "Address: " + server.ToString(), + "Server IP Address: " + server.ToString(), "Client: " + GlobalVars.UserConfiguration.SelectedClient, "Map: " + GlobalVars.UserConfiguration.Map, "Players: " + GlobalVars.UserConfiguration.PlayerLimit, @@ -608,24 +608,6 @@ public static class RobloxXML return ""; } - public static void DownloadFilesFromNode(string url, string path, string fileext, string id) - { - if (!string.IsNullOrWhiteSpace(id)) - { - Downloader download = new Downloader(url, id); - download.InitDownload(path, fileext, "", true, false); - if (download.getDownloadOutcome().Contains("Error")) - { - Util.ConsolePrint("Download Outcome: " + download.getDownloadOutcome(), 2); - throw new IOException(download.getDownloadOutcome()); - } - else - { - Util.ConsolePrint("Download Outcome: " + download.getDownloadOutcome(), 3); - } - } - } - public static string GetURLInNodes(XDocument doc, string itemClassValue, string itemIdValue, string url) { var v = from nodes in doc.Descendants("Item") diff --git a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs index 0426fc1..ec82ae9 100644 --- a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs +++ b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs @@ -322,10 +322,10 @@ namespace NovetusLauncher Util.ConsolePrint("ReShade DLL deletion disabled.", 4); } break; - case string altserverip when altserverip.Contains("altserverip", StringComparison.InvariantCultureIgnoreCase) == true: + case string altip when altip.Contains("altip", StringComparison.InvariantCultureIgnoreCase) == true: try { - string[] vals = altserverip.Split(' '); + string[] vals = altip.Split(' '); if (vals[1].Equals("none", StringComparison.InvariantCultureIgnoreCase)) { @@ -335,12 +335,12 @@ namespace NovetusLauncher else { GlobalVars.UserConfiguration.AlternateServerIP = vals[1]; - Util.ConsolePrint("Alternate Server IP set to " + vals[1], 4); + Util.ConsolePrint("Alternate Server IP set to " + GlobalVars.UserConfiguration.AlternateServerIP, 4); } } catch (Exception) { - Util.ConsolePrint("Please specify the IP address you would like to set Novetus to.", 2); + Util.ConsolePrint("Please specify the IP address you would like to set Novetus to. Type 'none' to disable this.", 2); } break; case string clear when clear.Contains("clear", StringComparison.InvariantCultureIgnoreCase) == true: diff --git a/Novetus/NovetusLauncher/Forms/SDK/AssetFixer.cs b/Novetus/NovetusLauncher/Forms/SDK/AssetFixer.cs index b538668..3570ba5 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/AssetFixer.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/AssetFixer.cs @@ -160,6 +160,25 @@ public partial class AssetFixer : Form AssetFixer_ProgressLabel.Text = "Progress: " + AssetFixer_ProgressBar.Value.ToString() + "/" + AssetFixer_ProgressBar.Maximum.ToString(); } + public static void DownloadFilesFromNode(string url, string path, string fileext, string id) + { + if (!string.IsNullOrWhiteSpace(id)) + { + Downloader download = new Downloader(url, id); + download.setDownloadOptions(false, false); + download.InitDownloadDirect(path, fileext, "", true); + if (download.getDownloadOutcome().Contains("Error")) + { + Util.ConsolePrint("Download Outcome: " + download.getDownloadOutcome(), 2); + throw new IOException(download.getDownloadOutcome()); + } + else + { + Util.ConsolePrint("Download Outcome: " + download.getDownloadOutcome(), 3); + } + } + } + public void FixURLSOrDownloadFromScript(string filepath, string savefilepath, string inGameDir, bool useURLs, string url) { string[] file = File.ReadAllLines(filepath); @@ -253,7 +272,7 @@ public partial class AssetFixer : Form else { string IDVal = urlFixed.After(peram); - RobloxXML.DownloadFilesFromNode(urlFixed, savefilepath, "", IDVal); + DownloadFilesFromNode(urlFixed, savefilepath, "", IDVal); file[index - 1] = file[index - 1].Replace(link, inGameDir + IDVal); } } diff --git a/Novetus/NovetusLauncher/Novetus.Launcher.csproj b/Novetus/NovetusLauncher/Novetus.Launcher.csproj index 7c04c47..b348647 100644 --- a/Novetus/NovetusLauncher/Novetus.Launcher.csproj +++ b/Novetus/NovetusLauncher/Novetus.Launcher.csproj @@ -86,8 +86,8 @@ - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Portable.BouncyCastle.1.8.8\lib\net40\BouncyCastle.Crypto.dll + + ..\packages\Portable.BouncyCastle.1.9.0\lib\net40\BouncyCastle.Crypto.dll C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\BrotliSharpLib.0.3.3\lib\net451\BrotliSharpLib.dll @@ -99,11 +99,11 @@ C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll - - ..\packages\Mono.Nat.1.2.24.0\lib\net40\Mono.Nat.dll + + ..\packages\Mono.Nat.3.0.4\lib\netstandard2.0\Mono.Nat.dll - ..\packages\NLog.5.0.5\lib\net35\NLog.dll + ..\packages\NLog.5.1.0\lib\net46\NLog.dll @@ -121,21 +121,22 @@ 3.5 + - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + + ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.AccessControl.5.0.0\lib\net461\System.Security.AccessControl.dll + + ..\packages\System.Security.AccessControl.6.0.0\lib\net461\System.Security.AccessControl.dll C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll @@ -152,8 +153,8 @@ 3.5 - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Titanium.Web.Proxy.3.1.1450\lib\net461\Titanium.Web.Proxy.dll + + ..\packages\Titanium.Web.Proxy.3.2.0\lib\net461\Titanium.Web.Proxy.dll diff --git a/Novetus/NovetusLauncher/app.config b/Novetus/NovetusLauncher/app.config index b1e96f4..519a38a 100644 --- a/Novetus/NovetusLauncher/app.config +++ b/Novetus/NovetusLauncher/app.config @@ -1,19 +1,31 @@ - + - + - - + + - - + + + + + + + + + + + + + + - + diff --git a/Novetus/NovetusLauncher/packages.config b/Novetus/NovetusLauncher/packages.config index c79bdf4..a316aab 100644 --- a/Novetus/NovetusLauncher/packages.config +++ b/Novetus/NovetusLauncher/packages.config @@ -2,19 +2,16 @@ - - - - - - + + + - + - - + + - + \ No newline at end of file diff --git a/Novetus/NovetusURI/App.config b/Novetus/NovetusURI/App.config index c101a1b..a99a8bb 100644 --- a/Novetus/NovetusURI/App.config +++ b/Novetus/NovetusURI/App.config @@ -13,6 +13,18 @@ + + + + + + + + + + + + diff --git a/Novetus/NovetusURI/Novetus.URI.csproj b/Novetus/NovetusURI/Novetus.URI.csproj index 3c38e3c..a2e1e3c 100644 --- a/Novetus/NovetusURI/Novetus.URI.csproj +++ b/Novetus/NovetusURI/Novetus.URI.csproj @@ -47,8 +47,8 @@ app.manifest - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Portable.BouncyCastle.1.8.8\lib\net40\BouncyCastle.Crypto.dll + + ..\packages\Portable.BouncyCastle.1.9.0\lib\net40\BouncyCastle.Crypto.dll C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\BrotliSharpLib.0.3.3\lib\net451\BrotliSharpLib.dll @@ -56,11 +56,11 @@ C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll - - ..\packages\Mono.Nat.1.2.24.0\lib\net40\Mono.Nat.dll + + ..\packages\Mono.Nat.3.0.4\lib\netstandard2.0\Mono.Nat.dll - ..\packages\NLog.5.0.5\lib\net35\NLog.dll + ..\packages\NLog.5.1.0\lib\net46\NLog.dll @@ -68,21 +68,22 @@ + - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + + ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.AccessControl.5.0.0\lib\net461\System.Security.AccessControl.dll + + ..\packages\System.Security.AccessControl.6.0.0\lib\net461\System.Security.AccessControl.dll C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll @@ -101,8 +102,8 @@ - - C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Titanium.Web.Proxy.3.1.1450\lib\net461\Titanium.Web.Proxy.dll + + ..\packages\Titanium.Web.Proxy.3.2.0\lib\net461\Titanium.Web.Proxy.dll diff --git a/Novetus/NovetusURI/packages.config b/Novetus/NovetusURI/packages.config index 543a2fd..530607d 100644 --- a/Novetus/NovetusURI/packages.config +++ b/Novetus/NovetusURI/packages.config @@ -1,19 +1,16 @@  - - - - - - + + + - + - - + + - + \ No newline at end of file diff --git a/changelog.txt b/changelog.txt index 28b4352..110853e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,8 +1,19 @@ 1.3 Snapshot v22.8342.20628.1 +Notes: +- As of the current Novetus version, .NET Framework 4.0 is no longer the main framework running Novetus. Novetus now requires .NET Framework 4.8. + Enhancements: +- Updated required libraries. +- Made the itch.io app support more user friendly. +- Clarified the Server IP Address in the server information panel more clearly. +- Made the healthbar in 2011E more accurate. (TODO: REVALIDATE CLIENT MD5s) +- Renamed altserverip to altip to fix miscellaneous issues with it. +- The Asset Fixer will now skip downloads of files with the same name. + Fixes: - Fixed bullets arcing in Rise of the Killbots (credits to Ae1ouRed) - Remastered audio in Rise of the Killbots to be less loud. +- Fixed various issues with the altip command. ---------------------------------------------------------------------------- 1.3 Snapshot v22.8342.20628.1 Enhancements: diff --git a/consolehelp.txt b/consolehelp.txt index a8a1122..4648bcf 100644 --- a/consolehelp.txt +++ b/consolehelp.txt @@ -9,7 +9,7 @@ Commands:|3 + studio nomap - Launches Roblox Studio without the selected map|4 + sdk - Launches the Novetus SDK Launcher|4 + dlldelete - Toggle the deletion of opengl32.dll when ReShade is off.|4 -+ altserverip - Sets the alternate server IP for server info. Replace with your specified IP or specify 'none' to remove the current alternate server IP|4 ++ altip - Sets the alternate server IP for server info. Replace with your specified IP or specify 'none' to remove the current alternate server IP|4 + clear - Clears all text in this window.|4 + help - Clears all text and shows this list.|4 + documentation - Clears all text and shows the ClientScript documentation.|4 diff --git a/scripts/batch/Novetus_launcher_admin.bat b/scripts/batch/Novetus_launcher_admin.bat deleted file mode 100644 index 056a77d..0000000 --- a/scripts/batch/Novetus_launcher_admin.bat +++ /dev/null @@ -1,26 +0,0 @@ -@ECHO OFF -REM --> https://superuser.com/questions/705813/batch-file-with-commands-to-run-as-administrator-and-standard-user -:: BatchGotAdmin -:------------------------------------- -REM --> Check for permissions ->nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" - -REM --> If error flag set, we do not have admin. -if '%errorlevel%' NEQ '0' ( - echo Requesting administrative privileges... - goto UACPrompt -) else ( goto gotAdmin ) - -:UACPrompt - echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" - echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs" - - "%temp%\getadmin.vbs" - exit /B - -:gotAdmin - if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" ) - pushd "%CD%" - CD /D "%~dp0" - -call "%CD%/Novetus_launcher.bat" diff --git a/scripts/batch/Novetus_launcher_legacy.bat b/scripts/batch/Novetus_launcher_legacy.bat deleted file mode 100644 index dd8edc6..0000000 --- a/scripts/batch/Novetus_launcher_legacy.bat +++ /dev/null @@ -1,77 +0,0 @@ -@ECHO OFF -setlocal -cd /d %~dp0 -:MENU -TITLE NOVETUS LEGACY LAUNCHER -CLS -ECHO --------------------------------------------------------------------------- -ECHO NhhhhhhhhhhN hsssoosssd -ECHO NyyyyhhhhyyhdN hoo++++++h -ECHO NyyyyyhhhhyyyhN hoo+++///h -ECHO NssssyyyyyhyyyhdN hoo+++///h -ECHO Nsossssyyyyyyyyyhm hsoo++///h -ECHO NsssssssssyyyyyyyhdN hssoo++//h -ECHO Nsssssssssssyyyyhhhdm hsssoo+++h -ECHO NyssssssssysyyyyhhhhhdN NNNNNmmmmdddddhhysoooo+++ymNN -ECHO Nhyyssssssmdyyyyhhhhhyhyysssssooooooooosssooooo++osssyhdmN -ECHO Nhyyyyssssddhyyyhhyyysssosyyhhhddmmmmmmmyooooo+++yhyssoosydN -ECHO NdhhyyyysssoosyhyyyssooooydN y++++++++hN NNdhsoohN -ECHO NmdhhhyyyysyhddmNmhyssooooooshN s++++++++h doosm -ECHO NNdhysoyyyysssssm NdsoooooooooydN s/////+++h NmyooyN -ECHO Ndysoosyhyysssooosm myooooooososhN s///////+h Ndhsoshm -ECHO mhsoosydmNmysooooooom NdssssssssooydN s////////hdhssosydN -ECHO NhsosydN Nsoooo+++om mhssssssoooohm y++/////+soosyhmN -ECHO NhoosdN Nsooo+++oom NdyssssooooosdN Ny++++oooosydmN -ECHO msood Noooooooosm Nhssooooooooydhysoooo++++hN -ECHO NhooshmN Nsoooooossm Nmhsoooooooooooso++////++h -ECHO Nhysossyhhdddoooooooosdmmmmmdddhhhyysssoooooooooo++ss++//++++h -ECHO Nmhyyssooooooooooooosssooooooossssyyhhdds+++++++++++++++oood -ECHO NNmmmddssooooooohhhhddddmmmNNNN Ny+++++++++++++osssd -ECHO Nyyssssoosm Nds+++++++++oosssyd -ECHO Nhyyysssssm Nho++++++oossssyd -ECHO Nyyyyyssssm ms+++++ooossssd -ECHO Nyyyssssssm Nho+++ooossssd -ECHO Nhyyyyyyyym mysssssyyyyd -ECHO --------------------------------------------------------------------------- -ECHO. -ECHO NOVETUS LEGACY LAUNCHER -ECHO. -ECHO 1 - Play -ECHO 2 - Play with Console -ECHO 3 = Install Required Dependencies -ECHO 4 - Novetus SDK -ECHO 5 - Novetus Console (Server Mode) -ECHO 6 - Novetus Console Help -ECHO 7 - Install URI -ECHO 8 - Exit -ECHO. -SET /P M=Choose an option by typing the number corresponding to which utility you want to launch: -IF %M%==1 CLS -IF %M%==1 start "" "%CD%/bin/Novetus.exe" -nocmd -IF %M%==1 EXIT - -IF %M%==2 CLS -IF %M%==2 start "" "%CD%/bin/Novetus.exe" -IF %M%==2 EXIT - -IF %M%==3 CLS -IF %M%==3 call "%CD%/Novetus_dependency_installer.bat" - -IF %M%==4 CLS -IF %M%==4 start "" "%CD%/bin/Novetus.exe" -sdk -IF %M%==4 EXIT - -IF %M%==5 CLS -IF %M%==5 start "" "%CD%/bin/Novetus.exe" -cmdonly -cmdmode -IF %M%==5 EXIT - -IF %M%==6 CLS -IF %M%==6 start "" "%CD%/bin/Novetus.exe" -cmdonly -help -IF %M%==6 EXIT - -IF %M%==7 CLS -IF %M%==7 start "" "%CD%/bin/NovetusURI.exe" -IF %M%==7 EXIT - -IF %M%==8 EXIT -EXIT diff --git a/scripts/batch/github_sync.bat b/scripts/batch/github_sync.bat index 0004d34..159af7c 100644 --- a/scripts/batch/github_sync.bat +++ b/scripts/batch/github_sync.bat @@ -146,7 +146,6 @@ XCOPY "%cd%\clean_junk.bat" "%scriptsdir%\batch" /y XCOPY "%cd%\github_sync.bat" "%scriptsdir%\batch" /y XCOPY "%cd%\assetfixer_gauntlet.lua" "%scriptsdir%" /y XCOPY "%cd%\Novetus\Novetus_dependency_installer.bat" "%scriptsdir%\batch" /y -XCOPY "%cd%\Novetus\Novetus_launcher_legacy.bat" "%scriptsdir%\batch" /y XCOPY "%cd%\Novetus\documentation.txt" "%dest%" /y XCOPY "%cd%\Novetus\consolehelp.txt" "%dest%" /y XCOPY /c "%cd%\Novetus\.itch.toml" "%dest%" /y -- 2.40.1 From f8d1f9406cd7b1c0f73440f7f863c734f9cf76c0 Mon Sep 17 00:00:00 2001 From: Bitl Date: Thu, 22 Dec 2022 06:47:16 -0700 Subject: [PATCH 05/85] Update LauncherFormSettings.Designer.cs --- .../Forms/LauncherFormSettings.Designer.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Novetus/NovetusLauncher/Forms/LauncherFormSettings.Designer.cs b/Novetus/NovetusLauncher/Forms/LauncherFormSettings.Designer.cs index 59908fb..8711539 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherFormSettings.Designer.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherFormSettings.Designer.cs @@ -105,7 +105,7 @@ // checkBox7 // this.checkBox7.AutoSize = true; - this.checkBox7.Location = new System.Drawing.Point(6, 43); + this.checkBox7.Location = new System.Drawing.Point(6, 42); this.checkBox7.Name = "checkBox7"; this.checkBox7.Size = new System.Drawing.Size(164, 17); this.checkBox7.TabIndex = 77; @@ -125,11 +125,11 @@ // checkBox5 // this.checkBox5.AutoSize = true; - this.checkBox5.Location = new System.Drawing.Point(6, 14); + this.checkBox5.Location = new System.Drawing.Point(6, 20); this.checkBox5.Name = "checkBox5"; - this.checkBox5.Size = new System.Drawing.Size(184, 30); + this.checkBox5.Size = new System.Drawing.Size(107, 17); this.checkBox5.TabIndex = 75; - this.checkBox5.Text = "Toggle ReShade \r\n(Windows 7 SP1 and above only)"; + this.checkBox5.Text = "Toggle ReShade"; this.checkBox5.UseVisualStyleBackColor = true; this.checkBox5.CheckedChanged += new System.EventHandler(this.checkBox5_CheckedChanged); // -- 2.40.1 From 220f4d3d75576e3459abcd917af4e354eda8dbba Mon Sep 17 00:00:00 2001 From: Bitl Date: Thu, 22 Dec 2022 07:29:02 -0700 Subject: [PATCH 06/85] begin work on clientscript 2. i got it to be backward compatible apparently. --- .../StorageAndFunctions/ClientManagement.cs | 235 +++++++++++++----- 1 file changed, 171 insertions(+), 64 deletions(-) diff --git a/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs b/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs index 5e33925..f1b2e4c 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs @@ -1024,6 +1024,48 @@ public class ClientManagement #endif } +#if URI + public static void ValidateFiles(string line, string validstart, string validend, Label label) +#else + public static void ValidateFiles(string line, string validstart, string validend) +#endif + { + string extractedFile = ScriptFuncs.ClientScript.GetArgsFromTag(line, validstart, validend); + if (!string.IsNullOrWhiteSpace(extractedFile)) + { + string[] parsedFileParams = extractedFile.Split('|'); + string filePath = parsedFileParams[0]; + string fileMD5 = parsedFileParams[1]; + string fullFilePath = GlobalPaths.ClientDir + @"\\" + GlobalVars.UserConfiguration.SelectedClient + @"\\" + filePath; + + if (!SecurityFuncs.CheckMD5(fileMD5, fullFilePath)) + { +#if URI + UpdateStatus(label, "The client has been detected as modified."); +#elif LAUNCHER + Util.ConsolePrint("ERROR - Failed to launch Novetus. (The client has been detected as modified.)", 2); +#endif + +#if LAUNCHER + if (!GlobalVars.isConsoleOnly) + { + MessageBox.Show("Failed to launch Novetus. (Error: The client has been detected as modified.)", "Novetus - Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } +#endif + +#if URI + throw new IOException("The client has been detected as modified."); +#else + return; +#endif + } + else + { + GlobalVars.ValidatedExtraFiles += 1; + } + } + } + #if URI public static void LaunchRBXClient(string ClientName, ScriptType type, bool no3d, bool nomap, EventHandler e, Label label) #else @@ -1110,61 +1152,63 @@ public class ClientManagement string args = ""; GlobalVars.ValidatedExtraFiles = 0; + bool v1 = false; + + if (info.CommandLineArgs.Contains("<") && + info.CommandLineArgs.Contains("")) + { + v1 = true; + } + if (!GlobalVars.AdminMode && !info.AlreadyHasSecurity) { string validstart = ""; string validend = ""; + string validv2 = "validate="; foreach (string line in info.CommandLineArgs.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)) { - if (line.Contains(validstart) && line.Contains(validend)) + if (v1 && line.Contains(validstart) && line.Contains(validend)) { - string extractedFile = ScriptFuncs.ClientScript.GetArgsFromTag(line, validstart, validend); - if (!string.IsNullOrWhiteSpace(extractedFile)) + try { - try - { - string[] parsedFileParams = extractedFile.Split('|'); - string filePath = parsedFileParams[0]; - string fileMD5 = parsedFileParams[1]; - string fullFilePath = GlobalPaths.ClientDir + @"\\" + GlobalVars.UserConfiguration.SelectedClient + @"\\" + filePath; - - if (!SecurityFuncs.CheckMD5(fileMD5, fullFilePath)) - { #if URI - UpdateStatus(label, "The client has been detected as modified."); -#elif LAUNCHER - Util.ConsolePrint("ERROR - Failed to launch Novetus. (The client has been detected as modified.)", 2); -#endif - -#if LAUNCHER - if (!GlobalVars.isConsoleOnly) - { - MessageBox.Show("Failed to launch Novetus. (Error: The client has been detected as modified.)", "Novetus - Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } -#endif - -#if URI - throw new IOException("The client has been detected as modified."); + ValidateFiles(line, validstart, validend, label); #else - return; + ValidateFiles(line, validstart, validend); #endif - } - else - { - GlobalVars.ValidatedExtraFiles += 1; - } - } + } #if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); + catch (Exception ex) + { + Util.LogExceptions(ex); #else - catch (Exception) - { + catch (Exception) + { #endif - continue; - } + continue; + } + } + else if (line.Contains(validv2)) + { + try + { +#if URI + ValidateFiles(line, validv2, "", label); +#else + ValidateFiles(line, validv2, ""); +#endif + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); +#else + catch (Exception) + { +#endif + continue; } } } @@ -1198,8 +1242,8 @@ public class ClientManagement else { args = ScriptFuncs.ClientScript.CompileScript(ClientName, info.CommandLineArgs, - ScriptFuncs.ClientScript.GetTagFromType(type, false, no3d), - ScriptFuncs.ClientScript.GetTagFromType(type, true, no3d), + ScriptFuncs.ClientScript.GetTagFromType(type, false, no3d, v1), + ScriptFuncs.ClientScript.GetTagFromType(type, true, no3d, v1), mapfile, luafile, rbxexe); @@ -1552,10 +1596,19 @@ public class ScriptFuncs { try { - int pFrom = code.IndexOf(tag) + tag.Length; - int pTo = code.LastIndexOf(endtag); - string result = code.Substring(pFrom, pTo - pFrom); - return result; + if (string.IsNullOrEmpty(endtag)) + { + //VERSION 2!! + string result = code.Substring(code.IndexOf(tag) + tag.Length); + return result; + } + else + { + int pFrom = code.IndexOf(tag) + tag.Length; + int pTo = code.LastIndexOf(endtag); + string result = code.Substring(pFrom, pTo - pFrom); + return result; + } } #if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) @@ -1587,20 +1640,45 @@ public class ScriptFuncs } } - public static string GetTagFromType(ScriptType type, bool endtag, bool no3d) + public static string GetTagFromType(ScriptType type, bool endtag, bool no3d, bool v1) { - switch (type) + if (v1) { - case ScriptType.Client: - return endtag ? "" : ""; - case ScriptType.Server: - return no3d ? (endtag ? "" : "") : (endtag ? "" : ""); - case ScriptType.Solo: - return endtag ? "" : ""; - case ScriptType.Studio: - return endtag ? "" : ""; - default: + switch (type) + { + case ScriptType.Client: + return endtag ? "" : ""; + case ScriptType.Server: + return no3d ? (endtag ? "" : "") : (endtag ? "" : ""); + case ScriptType.Solo: + return endtag ? "" : ""; + case ScriptType.Studio: + return endtag ? "" : ""; + default: + return ""; + } + } + else + { + if (endtag == true) + { + //NO END TAGS. return ""; + } + + switch (type) + { + case ScriptType.Client: + return "client="; + case ScriptType.Server: + return no3d ? "no3d=" : "server="; + case ScriptType.Solo: + return "solo="; + case ScriptType.Studio: + return "studio="; + default: + return ""; + } } } @@ -1676,25 +1754,54 @@ public class ScriptFuncs string start = tag; string end = endtag; + bool v1 = false; + + if (code.Contains("<") && + code.Contains("")) + { + v1 = true; + } + else + { + //make sure we have no end tags. + if (!string.IsNullOrWhiteSpace(end)) + { + end = ""; + } + } + FileFormat.ClientInfo info = ClientManagement.GetClientInfoValues(ClientName); ScriptType type = GetTypeFromTag(start); //we must have the ending tag before we continue. - if (string.IsNullOrWhiteSpace(end)) + if (v1 && string.IsNullOrWhiteSpace(end)) { return ""; } if (usesharedtags) { - string sharedstart = ""; - string sharedend = ""; - - if (code.Contains(sharedstart) && code.Contains(sharedend)) + if (v1) { - start = sharedstart; - end = sharedend; + string sharedstart = ""; + string sharedend = ""; + + if (code.Contains(sharedstart) && code.Contains(sharedend)) + { + start = sharedstart; + end = sharedend; + } + } + else + { + string sharedstart = "shared="; + + if (code.Contains(sharedstart)) + { + start = sharedstart; + } } } -- 2.40.1 From 12ebe07de4089332dbc9a3d33b0703f5d5334ef1 Mon Sep 17 00:00:00 2001 From: Bitl Date: Thu, 22 Dec 2022 08:20:14 -0700 Subject: [PATCH 07/85] cleanup --- .../StorageAndFunctions/ClientManagement.cs | 15 +--- .../Forms/SDK/ClientinfoCreator.Designer.cs | 90 ++++++------------- .../Forms/SDK/ClientinfoCreator.cs | 16 ++-- 3 files changed, 34 insertions(+), 87 deletions(-) diff --git a/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs b/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs index f1b2e4c..162621a 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs @@ -1618,7 +1618,7 @@ public class ScriptFuncs catch (Exception) { #endif - return "%donothing%"; + return ""; } } @@ -1811,12 +1811,6 @@ public class ScriptFuncs } string extractedCode = GetArgsFromTag(code, start, end); - - if (extractedCode.Contains("%donothing%")) - { - return ""; - } - #if LAUNCHER string md5dir = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(Assembly.GetExecutingAssembly().Location) : ""; #else @@ -1878,7 +1872,6 @@ public class ScriptFuncs .Replace("%scripttype%", Generator.GetNameForType(type)) .Replace("%notifications%", GlobalVars.UserConfiguration.ShowServerNotifications.ToString().ToLower()) .Replace("%loadout%", code.Contains("") ? GlobalVars.soloLoadout : GlobalVars.Loadout) - .Replace("%doublequote%", "\"") .Replace("%validatedextrafiles%", GlobalVars.ValidatedExtraFiles.ToString()) .Replace("%argstring%", GetRawArgsForType(type, ClientName, luafile)) .Replace("%tshirttexid%", GlobalVars.TShirtTextureID) @@ -1891,12 +1884,6 @@ public class ScriptFuncs .Replace("%facetexlocal%", GlobalVars.FaceTextureLocal) .Replace("%newgui%", GlobalVars.UserConfiguration.NewGUI.ToString().ToLower()); - if (compiled.Contains("%disabled%")) - { - MessageBox.Show("This option has been disabled for this client.", "Novetus - Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - return ""; - } - return compiled; } } diff --git a/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.Designer.cs b/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.Designer.cs index 625e468..fc26463 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.Designer.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.Designer.cs @@ -74,7 +74,6 @@ partial class ClientinfoEditor this.ipToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.scripttypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.versionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.doublequoteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.joinportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.validatedextrafilesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.argstringToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -84,6 +83,7 @@ partial class ClientinfoEditor this.useloadfileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.userbxassetforgenerationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.generatescriptToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.serverToolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); this.serverToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.limitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.notificationsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -148,9 +148,6 @@ partial class ClientinfoEditor this.nameToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.idToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.tripcodeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.debuggingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.donothingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.disabledToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.argsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.documentationToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.textBox4 = new System.Windows.Forms.TextBox(); @@ -166,7 +163,6 @@ partial class ClientinfoEditor this.checkBox8 = new System.Windows.Forms.CheckBox(); this.textBox2 = new System.Windows.Forms.TextBox(); this.label3 = new System.Windows.Forms.Label(); - this.serverToolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); this.menuStrip1.SuspendLayout(); this.SuspendLayout(); // @@ -369,42 +365,42 @@ partial class ClientinfoEditor // this.clientToolStripMenuItem.Name = "clientToolStripMenuItem"; this.clientToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.clientToolStripMenuItem.Text = ""; + this.clientToolStripMenuItem.Text = "client="; this.clientToolStripMenuItem.Click += new System.EventHandler(this.clientToolStripMenuItem_Click); // // serverToolStripMenuItem // this.serverToolStripMenuItem.Name = "serverToolStripMenuItem"; this.serverToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.serverToolStripMenuItem.Text = ""; + this.serverToolStripMenuItem.Text = "server="; this.serverToolStripMenuItem.Click += new System.EventHandler(this.serverToolStripMenuItem_Click); // // soloToolStripMenuItem // this.soloToolStripMenuItem.Name = "soloToolStripMenuItem"; this.soloToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.soloToolStripMenuItem.Text = ""; + this.soloToolStripMenuItem.Text = "solo="; this.soloToolStripMenuItem.Click += new System.EventHandler(this.soloToolStripMenuItem_Click); // // studioToolStripMenuItem // this.studioToolStripMenuItem.Name = "studioToolStripMenuItem"; this.studioToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.studioToolStripMenuItem.Text = ""; + this.studioToolStripMenuItem.Text = "studio="; this.studioToolStripMenuItem.Click += new System.EventHandler(this.studioToolStripMenuItem_Click); // // no3dToolStripMenuItem // this.no3dToolStripMenuItem.Name = "no3dToolStripMenuItem"; this.no3dToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.no3dToolStripMenuItem.Text = ""; + this.no3dToolStripMenuItem.Text = "no3d="; this.no3dToolStripMenuItem.Click += new System.EventHandler(this.no3dToolStripMenuItem_Click); // // sharedToolStripMenuItem // this.sharedToolStripMenuItem.Name = "sharedToolStripMenuItem"; this.sharedToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.sharedToolStripMenuItem.Text = ""; + this.sharedToolStripMenuItem.Text = "shared="; this.sharedToolStripMenuItem.Click += new System.EventHandler(this.sharedToolStripMenuItem_Click); // // validateToolStripMenuItem @@ -413,7 +409,7 @@ partial class ClientinfoEditor this.addValidateTagsForRelativePathToolStripMenuItem}); this.validateToolStripMenuItem.Name = "validateToolStripMenuItem"; this.validateToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.validateToolStripMenuItem.Text = ""; + this.validateToolStripMenuItem.Text = "validate="; this.validateToolStripMenuItem.Click += new System.EventHandler(this.validateToolStripMenuItem_Click); // // addValidateTagsForRelativePathToolStripMenuItem @@ -430,7 +426,6 @@ partial class ClientinfoEditor this.serverToolStripMenuItem1, this.securityToolStripMenuItem, this.playerToolStripMenuItem, - this.debuggingToolStripMenuItem, this.argsToolStripMenuItem}); this.variablesToolStripMenuItem.Name = "variablesToolStripMenuItem"; this.variablesToolStripMenuItem.Size = new System.Drawing.Size(180, 22); @@ -446,7 +441,6 @@ partial class ClientinfoEditor this.ipToolStripMenuItem, this.scripttypeToolStripMenuItem, this.versionToolStripMenuItem, - this.doublequoteToolStripMenuItem, this.joinportToolStripMenuItem, this.validatedextrafilesToolStripMenuItem, this.argstringToolStripMenuItem, @@ -510,13 +504,6 @@ partial class ClientinfoEditor this.versionToolStripMenuItem.Text = "%version%"; this.versionToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); // - // doublequoteToolStripMenuItem - // - this.doublequoteToolStripMenuItem.Name = "doublequoteToolStripMenuItem"; - this.doublequoteToolStripMenuItem.Size = new System.Drawing.Size(227, 22); - this.doublequoteToolStripMenuItem.Text = "%doublequote%"; - this.doublequoteToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); - // // joinportToolStripMenuItem // this.joinportToolStripMenuItem.Name = "joinportToolStripMenuItem"; @@ -580,6 +567,13 @@ partial class ClientinfoEditor this.generatescriptToolStripMenuItem.Text = "%generatescript%"; this.generatescriptToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); // + // serverToolStripMenuItem2 + // + this.serverToolStripMenuItem2.Name = "serverToolStripMenuItem2"; + this.serverToolStripMenuItem2.Size = new System.Drawing.Size(227, 22); + this.serverToolStripMenuItem2.Text = "%server%"; + this.serverToolStripMenuItem2.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); + // // serverToolStripMenuItem1 // this.serverToolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -593,21 +587,21 @@ partial class ClientinfoEditor // limitToolStripMenuItem // this.limitToolStripMenuItem.Name = "limitToolStripMenuItem"; - this.limitToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.limitToolStripMenuItem.Size = new System.Drawing.Size(160, 22); this.limitToolStripMenuItem.Text = "%limit%"; this.limitToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); // // notificationsToolStripMenuItem // this.notificationsToolStripMenuItem.Name = "notificationsToolStripMenuItem"; - this.notificationsToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.notificationsToolStripMenuItem.Size = new System.Drawing.Size(160, 22); this.notificationsToolStripMenuItem.Text = "%notifications%"; this.notificationsToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); // // portToolStripMenuItem // this.portToolStripMenuItem.Name = "portToolStripMenuItem"; - this.portToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.portToolStripMenuItem.Size = new System.Drawing.Size(160, 22); this.portToolStripMenuItem.Text = "%port%"; this.portToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); // @@ -628,49 +622,49 @@ partial class ClientinfoEditor // md5launcherToolStripMenuItem // this.md5launcherToolStripMenuItem.Name = "md5launcherToolStripMenuItem"; - this.md5launcherToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.md5launcherToolStripMenuItem.Size = new System.Drawing.Size(164, 22); this.md5launcherToolStripMenuItem.Text = "%md5launcher%"; this.md5launcherToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); // // md5scriptToolStripMenuItem // this.md5scriptToolStripMenuItem.Name = "md5scriptToolStripMenuItem"; - this.md5scriptToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.md5scriptToolStripMenuItem.Size = new System.Drawing.Size(164, 22); this.md5scriptToolStripMenuItem.Text = "%md5script%"; this.md5scriptToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); // // md5exeToolStripMenuItem // this.md5exeToolStripMenuItem.Name = "md5exeToolStripMenuItem"; - this.md5exeToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.md5exeToolStripMenuItem.Size = new System.Drawing.Size(164, 22); this.md5exeToolStripMenuItem.Text = "%md5exe%"; this.md5exeToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); // // md5scriptdToolStripMenuItem // this.md5scriptdToolStripMenuItem.Name = "md5scriptdToolStripMenuItem"; - this.md5scriptdToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.md5scriptdToolStripMenuItem.Size = new System.Drawing.Size(164, 22); this.md5scriptdToolStripMenuItem.Text = "%md5scriptd%"; this.md5scriptdToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); // // md5exedToolStripMenuItem // this.md5exedToolStripMenuItem.Name = "md5exedToolStripMenuItem"; - this.md5exedToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.md5exedToolStripMenuItem.Size = new System.Drawing.Size(164, 22); this.md5exedToolStripMenuItem.Text = "%md5exed%"; this.md5exedToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); // // md5sToolStripMenuItem // this.md5sToolStripMenuItem.Name = "md5sToolStripMenuItem"; - this.md5sToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.md5sToolStripMenuItem.Size = new System.Drawing.Size(164, 22); this.md5sToolStripMenuItem.Text = "%md5s%"; this.md5sToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); // // md5sdToolStripMenuItem // this.md5sdToolStripMenuItem.Name = "md5sdToolStripMenuItem"; - this.md5sdToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.md5sdToolStripMenuItem.Size = new System.Drawing.Size(164, 22); this.md5sdToolStripMenuItem.Text = "%md5sd%"; this.md5sdToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); // @@ -1089,29 +1083,6 @@ partial class ClientinfoEditor this.tripcodeToolStripMenuItem.Text = "%tripcode%"; this.tripcodeToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); // - // debuggingToolStripMenuItem - // - this.debuggingToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.donothingToolStripMenuItem, - this.disabledToolStripMenuItem}); - this.debuggingToolStripMenuItem.Name = "debuggingToolStripMenuItem"; - this.debuggingToolStripMenuItem.Size = new System.Drawing.Size(180, 22); - this.debuggingToolStripMenuItem.Text = "Debugging/Misc"; - // - // donothingToolStripMenuItem - // - this.donothingToolStripMenuItem.Name = "donothingToolStripMenuItem"; - this.donothingToolStripMenuItem.Size = new System.Drawing.Size(150, 22); - this.donothingToolStripMenuItem.Text = "%donothing%"; - this.donothingToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); - // - // disabledToolStripMenuItem - // - this.disabledToolStripMenuItem.Name = "disabledToolStripMenuItem"; - this.disabledToolStripMenuItem.Size = new System.Drawing.Size(150, 22); - this.disabledToolStripMenuItem.Text = "%disabled%"; - this.disabledToolStripMenuItem.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); - // // argsToolStripMenuItem // this.argsToolStripMenuItem.Name = "argsToolStripMenuItem"; @@ -1279,13 +1250,6 @@ partial class ClientinfoEditor this.label3.TabIndex = 37; this.label3.Text = "EXE Name:"; // - // serverToolStripMenuItem2 - // - this.serverToolStripMenuItem2.Name = "serverToolStripMenuItem2"; - this.serverToolStripMenuItem2.Size = new System.Drawing.Size(227, 22); - this.serverToolStripMenuItem2.Text = "%server%"; - this.serverToolStripMenuItem2.Click += new System.EventHandler(this.variableToolStripMenuItem_Click); - // // ClientinfoEditor // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -1395,7 +1359,6 @@ partial class ClientinfoEditor private System.Windows.Forms.ToolStripMenuItem tripcodeToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem iconeToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem iconToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem debuggingToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem argsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem faceToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem facedToolStripMenuItem; @@ -1410,7 +1373,6 @@ partial class ClientinfoEditor private System.Windows.Forms.ToolStripMenuItem extraToolStripMenuItem1; private System.Windows.Forms.ToolStripMenuItem extradToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem hat4dToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem donothingToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem charappToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem documentationToolStripMenuItem1; private System.Windows.Forms.ToolStripMenuItem saveAsTextFileToolStripMenuItem; @@ -1428,8 +1390,6 @@ partial class ClientinfoEditor private System.Windows.Forms.ToolStripMenuItem loadoutToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem md5sToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem md5sdToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem doublequoteToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem disabledToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem notificationsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem joinportToolStripMenuItem; private System.Windows.Forms.CheckBox checkBox5; diff --git a/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.cs b/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.cs index a0e9386..16a2905 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.cs @@ -363,37 +363,37 @@ public partial class ClientinfoEditor : Form //tags private void clientToolStripMenuItem_Click(object sender, EventArgs e) { - AddClientinfoText(""); + AddClientinfoText("client="); } private void serverToolStripMenuItem_Click(object sender, EventArgs e) { - AddClientinfoText(""); + AddClientinfoText("server="); } private void soloToolStripMenuItem_Click(object sender, EventArgs e) { - AddClientinfoText(""); + AddClientinfoText("solo="); } private void studioToolStripMenuItem_Click(object sender, EventArgs e) { - AddClientinfoText(""); + AddClientinfoText("studio="); } private void no3dToolStripMenuItem_Click(object sender, EventArgs e) { - AddClientinfoText(""); + AddClientinfoText("no3d="); } private void sharedToolStripMenuItem_Click(object sender, EventArgs e) { - AddClientinfoText(""); + AddClientinfoText("shared="); } private void validateToolStripMenuItem_Click(object sender, EventArgs e) { - AddClientinfoText("[FILE PATH IN CLIENT DIRECTORY]|[FILE MD5]"); + AddClientinfoText("validate=[FILE PATH IN CLIENT DIRECTORY]|[FILE MD5]"); } private void variableToolStripMenuItem_Click(object sender, EventArgs e) @@ -443,7 +443,7 @@ public partial class ClientinfoEditor : Form { string fileMD5 = SecurityFuncs.GenerateMD5(file.FullName); string filePathStrip = file.FullName.Replace(SelectedClientInfoPath, ""); - text.Add("" + filePathStrip.TrimStart('/', '\\') + "|" + fileMD5 + ""); + text.Add("validate=" + filePathStrip.TrimStart('/', '\\') + "|" + fileMD5); } string joined = string.Join("\r\n", text); -- 2.40.1 From 416406868d692fcdf566ee30131d3c17f810934d Mon Sep 17 00:00:00 2001 From: Bitl Date: Thu, 22 Dec 2022 08:22:51 -0700 Subject: [PATCH 08/85] snapshot release --- changelog.txt | 9 +++++---- documentation.txt | 23 +++++++++++------------ scripts/launcher/info.ini | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/changelog.txt b/changelog.txt index 110853e..c78551b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,4 @@ -1.3 Snapshot v22.8342.20628.1 +1.3 Snapshot v22.8391.14830.1 Notes: - As of the current Novetus version, .NET Framework 4.0 is no longer the main framework running Novetus. Novetus now requires .NET Framework 4.8. @@ -6,14 +6,15 @@ Enhancements: - Updated required libraries. - Made the itch.io app support more user friendly. - Clarified the Server IP Address in the server information panel more clearly. -- Made the healthbar in 2011E more accurate. (TODO: REVALIDATE CLIENT MD5s) -- Renamed altserverip to altip to fix miscellaneous issues with it. +- Made the healthbar in 2011E more accurate. - The Asset Fixer will now skip downloads of files with the same name. +- ClientScript gets a visual makeover, with more readable tags! +- Removed unnecessary ClientScript variables. Fixes: - Fixed bullets arcing in Rise of the Killbots (credits to Ae1ouRed) - Remastered audio in Rise of the Killbots to be less loud. -- Fixed various issues with the altip command. +- Renamed altserverip to altip to fix miscellaneous issues with it. ---------------------------------------------------------------------------- 1.3 Snapshot v22.8342.20628.1 Enhancements: diff --git a/documentation.txt b/documentation.txt index 27ac82e..e79d1a0 100644 --- a/documentation.txt +++ b/documentation.txt @@ -1,12 +1,16 @@ +Notes: +------------------ +Use ` in place of a normal double quote ("). Novetus will NOT read double quotes on their own in its current state. + List of tags: ------------------ - - Tag for Client. - - Tag for Server. - - Tag for Server No3D. - - Tag for Solo. - - Tag for Studio. - - Shared tag used for all types. - - Validates a file via MD5 in the following format: [FILE PATH IN CLIENT DIRECTORY]|[FILE MD5]. Only tag compatible with %args%. +client= - Tag for Client. +server= - Tag for Server. +no3d= - Tag for Server No3D. +solo= - Tag for Solo. +studio= - Tag for Studio. +shared= - Shared tag used for all types. +validate= - Validates a file via MD5 in the following format: [FILE PATH IN CLIENT DIRECTORY]|[FILE MD5]. Only tag compatible with %args%. List of variables: ------------------ @@ -20,7 +24,6 @@ General: %ip% - Current IP address. %scripttype% - Returns the type of script we are using as a string. %version% - Returns Novetus' version. -%doublequote% - Returns a double-quote character. Use in place of a normal double quote ("). %joinport% - Returns the port when joining a server. %validatedfiles% - Returns the total number of files that have been validated. %validatedextrafiles% - Returns the total number of files that have been validated with . @@ -61,10 +64,6 @@ Player: %tshirttexidlocal%, %shirttexidlocal%, %pantstexidlocal%, %facetexlocal%" - Returns the texture rbxasset URL for the respective online clothing type. Returns nothing if the URL is invalid, the item isn't using Online Clothing, or %localizeonlineclothing% is not defined in the script. %localizeonlineclothing% - Grabs texture IDS for the %texid% variables and localizes the texture for the %texidlocal% variables. This WILL increase load times of your client depending on how many items are being downloaded. -Debugging/Misc: -%donothing% - Does exactly as it implies. Useful for debugging tags, but doesn't need to be used as it is called automatically if there is an exception when reading tags. Used internally to suppress errors. -%disabled% - Disables the option from the launcher and displays a message upon script compilation. - Examples: ------------------ Barebones 2017 launcher: diff --git a/scripts/launcher/info.ini b/scripts/launcher/info.ini index ff02e34..e90a3fa 100644 --- a/scripts/launcher/info.ini +++ b/scripts/launcher/info.ini @@ -9,5 +9,5 @@ ExtendedVersionEditChangelog=True //ExtendedVersionTemplate=%version% v11.2022.%extended-revision%%lite% ExtendedVersionTemplate=%version% Snapshot v22.%build%.%revision%.%extended-revision% ExtendedVersionRevision=1 -InitialBootup=False +InitialBootup=True IsLite=False -- 2.40.1 From ceeff5b78d6b438b7450e2389961855597726ee3 Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 23 Dec 2022 12:43:55 -0700 Subject: [PATCH 09/85] untitled --- scripts/launcher/splashes.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/launcher/splashes.txt b/scripts/launcher/splashes.txt index 9705de1..925cf35 100644 --- a/scripts/launcher/splashes.txt +++ b/scripts/launcher/splashes.txt @@ -243,4 +243,5 @@ allows the user to use W... [stylish]I DROPPED MY PHONE IN MCDONALD'S SPRITE...|...AND THAT MOTHERFUCKER STARTED CHARGING!! [normal]I'm the Toa of... of... Anarchy. [stylish]My name is... ah... Toa Vezon. I'm the Toa of... of... Anarchy. -Your System ate a SPARC! Gah! \ No newline at end of file +Your System ate a SPARC! Gah! +Dedicated to Missie. \ No newline at end of file -- 2.40.1 From be8fa8a3d92ceed24122106d298db6b1696d8f93 Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 30 Dec 2022 11:38:57 -0700 Subject: [PATCH 10/85] prototype web server --- Novetus/NovetusCore/Classes/WebProxy.cs | 135 ++++++++++++++++++ Novetus/NovetusCore/NovetusCore.projitems | 1 + .../StorageAndFunctions/GlobalVars.cs | 6 +- .../Compact/LauncherFormCompact.cs | 2 +- .../Extended/LauncherFormExtended.cs | 2 +- .../Forms/LauncherForm/LauncherFormShared.cs | 9 +- .../LauncherFormStylishInterface.xaml.cs | 1 + .../NovetusLauncher/Forms/NovetusConsole.cs | 6 + .../NovetusLauncher/Novetus.Launcher.csproj | 1 + Novetus/NovetusURI/Forms/LoaderForm.cs | 5 + 10 files changed, 163 insertions(+), 5 deletions(-) create mode 100644 Novetus/NovetusCore/Classes/WebProxy.cs diff --git a/Novetus/NovetusCore/Classes/WebProxy.cs b/Novetus/NovetusCore/Classes/WebProxy.cs new file mode 100644 index 0000000..1754ee7 --- /dev/null +++ b/Novetus/NovetusCore/Classes/WebProxy.cs @@ -0,0 +1,135 @@ +#if LAUNCHER || URI +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using Titanium.Web.Proxy; +using Titanium.Web.Proxy.EventArguments; +using Titanium.Web.Proxy.Http; +using Titanium.Web.Proxy.Models; + +public class WebProxy +{ + private static ProxyServer Server = new ProxyServer(); + private static ExplicitProxyEndPoint end; + + public bool HasStarted() + { + return Server.ProxyRunning; + } + + public void Start() + { + try + { + //load ext + Server.BeforeRequest += new AsyncEventHandler(OnRequest); + UpdateEndPoint(true); + Util.ConsolePrint("Web Proxy started on port " + GlobalVars.WebProxyPort, 3); + } + catch (Exception e) + { + Util.LogExceptions(e); + } + } + + public void UpdateEndPoint(bool shouldRunServer = false, bool decrypt = true) + { + if (Server.ProxyEndPoints.Count > 0) + { + Server.RemoveEndPoint(end); + } + + GlobalVars.WebProxyPort = GlobalVars.UserConfiguration.RobloxPort + 1; + end = new ExplicitProxyEndPoint(IPAddress.Any, GlobalVars.WebProxyPort, decrypt); + end.BeforeTunnelConnectRequest += new AsyncEventHandler(OnBeforeTunnelConnectRequest); + Server.AddEndPoint(end); + + if (!Server.ProxyRunning && shouldRunServer) + { + Server.Start(); + } + + if (Server.ProxyRunning) + { + foreach (ProxyEndPoint endPoint in Server.ProxyEndPoints) + { + Server.SetAsSystemHttpProxy(end); + Server.SetAsSystemHttpsProxy(end); + } + } + + Util.ConsolePrint("Web Proxy Endpoint updated with port " + GlobalVars.WebProxyPort, 3); + } + + private bool IsURIAllowed(HttpWebClient client) + { + string uri = client.Request.RequestUri.Host; + + if ((!uri.StartsWith("www.") && + !uri.StartsWith("web.") && + !uri.StartsWith("assetgame.") && + !uri.StartsWith("wiki.") && + !uri.EndsWith("api.roblox.com") && + !uri.StartsWith("roblox.com") || !uri.EndsWith("roblox.com")) && + !uri.EndsWith("robloxlabs.com")) + { + return false; + } + + //we check the header + HeaderCollection headers = client.Request.Headers; + List userAgents = headers.GetHeaders("User-Agent"); + + if (userAgents == null) + return false; + + if (string.IsNullOrWhiteSpace(userAgents.FirstOrDefault().Value)) + return false; + + string ua = userAgents.FirstOrDefault().Value.ToLowerInvariant(); + + Util.ConsolePrint(ua); + + return ua.Contains("roblox"); + } + + private Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) + { + if (!IsURIAllowed(e.HttpClient)) + { + e.DecryptSsl = false; + } + + return Task.CompletedTask; + } + +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + private async Task OnRequest(object sender, SessionEventArgs e) +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously + { + if (!IsURIAllowed(e.HttpClient)) + { + return; + } + + Util.ConsolePrint("we should be returning a 404 here."); + e.GenericResponse("", HttpStatusCode.NotFound); + } + + public void Stop() + { + Util.ConsolePrint("Web Proxy stopping on port " + GlobalVars.WebProxyPort, 3); + Server.BeforeRequest -= new AsyncEventHandler(OnRequest); + Server.Stop(); + } +} + +public interface IWebProxyExtention +{ + +} +#endif diff --git a/Novetus/NovetusCore/NovetusCore.projitems b/Novetus/NovetusCore/NovetusCore.projitems index ae91e91..2657b69 100644 --- a/Novetus/NovetusCore/NovetusCore.projitems +++ b/Novetus/NovetusCore/NovetusCore.projitems @@ -9,6 +9,7 @@ NovetusCore + diff --git a/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs b/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs index 6854e80..bf0ea19 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs @@ -97,7 +97,11 @@ public static class GlobalVars public static string ExternalIP = SecurityFuncs.GetExternalIPAddress(); public static ScriptType GameOpened = ScriptType.None; public static string PlayerTripcode = ""; - #endregion +#if LAUNCHER || URI + public static int WebProxyPort = 0; + public static WebProxy Proxy = new WebProxy(); +#endif +#endregion #if LAUNCHER #region Novetus Launcher diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/Compact/LauncherFormCompact.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/Compact/LauncherFormCompact.cs index ff87595..63e2e34 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/Compact/LauncherFormCompact.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/Compact/LauncherFormCompact.cs @@ -183,7 +183,7 @@ namespace NovetusLauncher void Button22Click(object sender, EventArgs e) { - launcherForm.ResetCurPort(numericUpDown2, GlobalVars.UserConfiguration.RobloxPort); + launcherForm.ResetCurPort(numericUpDown2); } void TreeView1AfterSelect(object sender, TreeViewEventArgs e) diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/Extended/LauncherFormExtended.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/Extended/LauncherFormExtended.cs index ffd2ed2..2c77821 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/Extended/LauncherFormExtended.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/Extended/LauncherFormExtended.cs @@ -192,7 +192,7 @@ namespace NovetusLauncher void Button22Click(object sender, EventArgs e) { - launcherForm.ResetCurPort(numericUpDown2, GlobalVars.UserConfiguration.RobloxPort); + launcherForm.ResetCurPort(numericUpDown2); } void TreeView1AfterSelect(object sender, TreeViewEventArgs e) diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs index 82fc948..bab066e 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs @@ -186,6 +186,10 @@ namespace NovetusLauncher { DiscordRPC.Shutdown(); } + if (GlobalVars.Proxy.HasStarted()) + { + GlobalVars.Proxy.Stop(); + } if (!GlobalVars.AppClosed) { @@ -578,6 +582,7 @@ namespace NovetusLauncher Tree.Focus(); IPBox.Text = GlobalVars.CurrentServer.ToString(); HostPortBox.Value = Convert.ToDecimal(GlobalVars.UserConfiguration.RobloxPort); + GlobalVars.Proxy.UpdateEndPoint(); IPLabel.Text = GlobalVars.CurrentServer.ServerIP; PortLabel.Text = GlobalVars.CurrentServer.ServerPort.ToString(); DiscordPresenceCheckbox.Checked = GlobalVars.UserConfiguration.DiscordPresence; @@ -923,10 +928,9 @@ namespace NovetusLauncher IPBox.Text = GlobalVars.CurrentServer.ToString(); } - public void ResetCurPort(NumericUpDown box, int value) + public void ResetCurPort(NumericUpDown box) { box.Value = Convert.ToDecimal(GlobalVars.DefaultRobloxPort); - value = GlobalVars.DefaultRobloxPort; } public void ChangeServerAddress() @@ -953,6 +957,7 @@ namespace NovetusLauncher public void ChangeServerPort() { GlobalVars.UserConfiguration.RobloxPort = Convert.ToInt32(HostPortBox.Value); + GlobalVars.Proxy.UpdateEndPoint(); } public void ChangeClient() diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylishInterface.xaml.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylishInterface.xaml.cs index 40800d6..5aa55c0 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylishInterface.xaml.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylishInterface.xaml.cs @@ -340,6 +340,7 @@ namespace NovetusLauncher if (!IsLoaded) return; GlobalVars.UserConfiguration.RobloxPort = Convert.ToInt32(serverPortBox.Text); + GlobalVars.Proxy.UpdateEndPoint(); } private void maxPlayersBox_TextChanged(object sender, TextChangedEventArgs e) diff --git a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs index ec82ae9..3d4cd6c 100644 --- a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs +++ b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs @@ -125,6 +125,7 @@ namespace NovetusLauncher if (ConsoleArgs["hostport"] != null) { GlobalVars.UserConfiguration.RobloxPort = Convert.ToInt32(ConsoleArgs["hostport"]); + GlobalVars.Proxy.UpdateEndPoint(); } if (ConsoleArgs["upnp"] != null) @@ -356,6 +357,11 @@ namespace NovetusLauncher de.Show(); Util.ConsolePrint("???", 2); break; + case string proxy when proxy.Contains("proxytest", StringComparison.InvariantCultureIgnoreCase) == true: + GlobalVars.Proxy.Start(); + //Util.Delay(5000); + //GlobalVars.Proxy.Stop(); + break; default: Util.ConsolePrint("Command is either not registered or valid", 2); break; diff --git a/Novetus/NovetusLauncher/Novetus.Launcher.csproj b/Novetus/NovetusLauncher/Novetus.Launcher.csproj index b348647..563522b 100644 --- a/Novetus/NovetusLauncher/Novetus.Launcher.csproj +++ b/Novetus/NovetusLauncher/Novetus.Launcher.csproj @@ -127,6 +127,7 @@ ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll diff --git a/Novetus/NovetusURI/Forms/LoaderForm.cs b/Novetus/NovetusURI/Forms/LoaderForm.cs index 30b48fe..6ebc1da 100644 --- a/Novetus/NovetusURI/Forms/LoaderForm.cs +++ b/Novetus/NovetusURI/Forms/LoaderForm.cs @@ -107,6 +107,11 @@ namespace NovetusURI { GlobalVars.GameOpened = ScriptType.None; } + + if (GlobalVars.Proxy.HasStarted()) + { + GlobalVars.Proxy.Stop(); + } ClientManagement.UpdateRichPresence(ClientManagement.GetStateForType(GlobalVars.GameOpened)); Close(); } -- 2.40.1 From cfad6b29af67cf3836617c2a1205aaf5fb048027 Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 30 Dec 2022 11:51:58 -0700 Subject: [PATCH 11/85] fix proxy not working for roblox browser. complete proxy command. --- Novetus/NovetusCore/Classes/WebProxy.cs | 19 +++++++------- .../NovetusLauncher/Forms/NovetusConsole.cs | 26 ++++++++++++++++--- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/Novetus/NovetusCore/Classes/WebProxy.cs b/Novetus/NovetusCore/Classes/WebProxy.cs index 1754ee7..76ef906 100644 --- a/Novetus/NovetusCore/Classes/WebProxy.cs +++ b/Novetus/NovetusCore/Classes/WebProxy.cs @@ -69,12 +69,12 @@ public class WebProxy { string uri = client.Request.RequestUri.Host; - if ((!uri.StartsWith("www.") && - !uri.StartsWith("web.") && - !uri.StartsWith("assetgame.") && - !uri.StartsWith("wiki.") && - !uri.EndsWith("api.roblox.com") && - !uri.StartsWith("roblox.com") || !uri.EndsWith("roblox.com")) && + if ((!uri.StartsWith("www.") && + !uri.StartsWith("web.") && + !uri.StartsWith("assetgame.") && + !uri.StartsWith("wiki.") && + !uri.EndsWith("api.roblox.com") && + !uri.StartsWith("roblox.com") || !uri.EndsWith("roblox.com")) && !uri.EndsWith("robloxlabs.com")) { return false; @@ -92,9 +92,9 @@ public class WebProxy string ua = userAgents.FirstOrDefault().Value.ToLowerInvariant(); - Util.ConsolePrint(ua); - - return ua.Contains("roblox"); + //for some reason, this doesn't go through for the browser unless we look for mozilla/4.0. + //this shouldn't break modern mozilla browsers though. + return (ua.Contains("mozilla/4.0") || ua.Contains("roblox")); } private Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) @@ -116,7 +116,6 @@ public class WebProxy return; } - Util.ConsolePrint("we should be returning a 404 here."); e.GenericResponse("", HttpStatusCode.NotFound); } diff --git a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs index 3d4cd6c..bad4b05 100644 --- a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs +++ b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs @@ -357,10 +357,28 @@ namespace NovetusLauncher de.Show(); Util.ConsolePrint("???", 2); break; - case string proxy when proxy.Contains("proxytest", StringComparison.InvariantCultureIgnoreCase) == true: - GlobalVars.Proxy.Start(); - //Util.Delay(5000); - //GlobalVars.Proxy.Stop(); + case string proxy when proxy.Contains("proxy", StringComparison.InvariantCultureIgnoreCase) == true: + try + { + string[] vals = proxy.Split(' '); + + if (vals[1].Equals("on", StringComparison.InvariantCultureIgnoreCase)) + { + GlobalVars.Proxy.Start(); + } + else if (vals[1].Equals("off", StringComparison.InvariantCultureIgnoreCase)) + { + GlobalVars.Proxy.Stop(); + } + else + { + Util.ConsolePrint("Please specify 'on' or 'off'.", 2); + } + } + catch (Exception) + { + Util.ConsolePrint("Please specify 'on' or 'off'.", 2); + } break; default: Util.ConsolePrint("Command is either not registered or valid", 2); -- 2.40.1 From b0b2bad0196d5713a114ea02c75cc4300e8ed78b Mon Sep 17 00:00:00 2001 From: Bitl Date: Wed, 4 Jan 2023 09:20:17 -0700 Subject: [PATCH 12/85] polished proxy implementation, fix bugs --- Novetus/NovetusCore/Classes/WebProxy.cs | 39 +++++++ .../StorageAndFunctions/FileManagement.cs | 18 ++- .../NovetusCore/StorageAndFunctions/Util.cs | 105 ++++++++++++------ .../Forms/LauncherForm/LauncherFormShared.cs | 12 +- .../Stylish/LauncherFormStylish.cs | 14 +-- .../NovetusLauncher/Forms/NovetusConsole.cs | 55 ++++++++- Novetus/NovetusURI/Forms/QuickConfigure.cs | 1 + 7 files changed, 191 insertions(+), 53 deletions(-) diff --git a/Novetus/NovetusCore/Classes/WebProxy.cs b/Novetus/NovetusCore/Classes/WebProxy.cs index 76ef906..a54446d 100644 --- a/Novetus/NovetusCore/Classes/WebProxy.cs +++ b/Novetus/NovetusCore/Classes/WebProxy.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; +using System.Windows.Forms; using Titanium.Web.Proxy; using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.Http; @@ -21,11 +22,49 @@ public class WebProxy return Server.ProxyRunning; } + public void DoSetup() + { + if (GlobalVars.UserConfiguration.WebProxyInitialSetupRequired) + { + string text = "Would you like to enable the Novetus web proxy?\n\n" + + "A web proxy redirects web traffic to a different location and in some cases can act as a gateway to different sites. Novetus uses the web proxy for additional client features and asset redirection.\n\n" + + "When enabling the web proxy, Novetus will locally create a certificate upon startup that ensures the proxy's functionality. Novetus will not send any user data to anyone, as everything involving the web proxy is entirely local to this computer.\n" + + "If you have any issue connecting to other web sites, including Roblox, closing Novetus or typing 'proxy off' into Novetus' console will fix it in most instances.\n\n" + + "Upon pressing 'Yes', Windows will ask you for permission to install the certificate.\n\n" + + "You can change this option at any time by typing 'proxy disable' or 'proxy on' in the Novetus console. This message will appear only once.\n"; + + DialogResult result = MessageBox.Show(text, "Novetus - Web Proxy Opt-In", MessageBoxButtons.YesNo); + + switch (result) + { + case DialogResult.Yes: + GlobalVars.UserConfiguration.WebProxyEnabled = true; + Start(); + break; + case DialogResult.No: + default: + break; + } + + GlobalVars.UserConfiguration.WebProxyInitialSetupRequired = false; + FileManagement.Config(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ConfigName, true); + } + else + { + if (GlobalVars.UserConfiguration.WebProxyEnabled) + { + Start(); + } + } + } + public void Start() { try { //load ext + Server.CertificateManager.RootCertificateIssuerName = "Novetus"; + Server.CertificateManager.RootCertificateName = "Novetus Web Proxy"; Server.BeforeRequest += new AsyncEventHandler(OnRequest); UpdateEndPoint(true); Util.ConsolePrint("Web Proxy started on port " + GlobalVars.WebProxyPort, 3); diff --git a/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs b/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs index a383314..024a61f 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs @@ -89,6 +89,8 @@ public class FileFormat NewGUI = false; URIQuickConfigure = true; BootstrapperShowUI = true; + WebProxyInitialSetupRequired = true; + WebProxyEnabled = false; } public string SelectedClient { get; set; } @@ -120,6 +122,8 @@ public class FileFormat public bool NewGUI { get; set; } public bool URIQuickConfigure { get; set; } public bool BootstrapperShowUI { get; set; } + public bool WebProxyInitialSetupRequired { get; set; } + public bool WebProxyEnabled { get; set; } } #endregion @@ -831,6 +835,8 @@ public class FileManagement ini.IniWriteValue(section, "NewGUI", GlobalVars.UserConfiguration.NewGUI.ToString()); ini.IniWriteValue(section, "URIQuickConfigure", GlobalVars.UserConfiguration.URIQuickConfigure.ToString()); ini.IniWriteValue(section, "BootstrapperShowUI", GlobalVars.UserConfiguration.BootstrapperShowUI.ToString()); + ini.IniWriteValue(section, "WebProxyInitialSetupRequired", GlobalVars.UserConfiguration.WebProxyInitialSetupRequired.ToString()); + ini.IniWriteValue(section, "WebProxyEnabled", GlobalVars.UserConfiguration.WebProxyEnabled.ToString()); ConfigUseOldValIfExists(ini, section, "ItemMakerDisableHelpMessage", "AssetSDKDisableHelpMessage", GlobalVars.UserConfiguration.DisabledAssetSDKHelp.ToString(), write); ConfigUseOldValIfExists(ini, section, "AssetLocalizerSaveBackups", "AssetSDKFixerSaveBackups", GlobalVars.UserConfiguration.AssetSDKFixerSaveBackups.ToString(), write); @@ -850,7 +856,8 @@ public class FileManagement disablehelpmessage, discord, mappath, mapsnip, graphics, reshade, qualitylevel, style, savebackups, altIP, disReshadeDel, showNotifs, SB_Name, SB_Address, priority, - firstServerLaunch, newgui, quickconfigure, bootstrapper; + firstServerLaunch, newgui, quickconfigure, bootstrapper, + webproxysetup, webproxy; INIFile ini = new INIFile(cfgpath); @@ -881,6 +888,8 @@ public class FileManagement newgui = ini.IniReadValue(section, "NewGUI", GlobalVars.UserConfiguration.NewGUI.ToString()); quickconfigure = ini.IniReadValue(section, "URIQuickConfigure", GlobalVars.UserConfiguration.URIQuickConfigure.ToString()); bootstrapper = ini.IniReadValue(section, "BootstrapperShowUI", GlobalVars.UserConfiguration.BootstrapperShowUI.ToString()); + webproxysetup = ini.IniReadValue(section, "WebProxyInitialSetupRequired", GlobalVars.UserConfiguration.WebProxyInitialSetupRequired.ToString()); + webproxy = ini.IniReadValue(section, "WebProxyEnabled", GlobalVars.UserConfiguration.WebProxyEnabled.ToString()); disablehelpmessage = ConfigUseOldValIfExists(ini, section, "ItemMakerDisableHelpMessage", "AssetSDKDisableHelpMessage", GlobalVars.UserConfiguration.DisabledAssetSDKHelp.ToString(), write); savebackups = ConfigUseOldValIfExists(ini, section, "AssetLocalizerSaveBackups", "AssetSDKFixerSaveBackups", GlobalVars.UserConfiguration.AssetSDKFixerSaveBackups.ToString(), write); @@ -926,6 +935,8 @@ public class FileManagement GlobalVars.UserConfiguration.NewGUI = ValueBool(newgui, DefaultConfiguration.NewGUI); GlobalVars.UserConfiguration.URIQuickConfigure = ValueBool(quickconfigure, DefaultConfiguration.URIQuickConfigure); GlobalVars.UserConfiguration.BootstrapperShowUI = ValueBool(bootstrapper, DefaultConfiguration.BootstrapperShowUI); + GlobalVars.UserConfiguration.WebProxyInitialSetupRequired = ValueBool(webproxysetup, DefaultConfiguration.WebProxyInitialSetupRequired); + GlobalVars.UserConfiguration.WebProxyEnabled = ValueBool(webproxy, DefaultConfiguration.WebProxyEnabled); string oldMapath = Path.GetDirectoryName(GlobalVars.UserConfiguration.MapPath); //update the map path if the file doesn't exist and write to config. @@ -1325,6 +1336,9 @@ public class FileManagement public static void ResetConfigValues() #endif { + bool WebProxySetupComplete = GlobalVars.UserConfiguration.WebProxyInitialSetupRequired; + bool WebProxy = GlobalVars.UserConfiguration.WebProxyEnabled; + GlobalVars.UserConfiguration = new FileFormat.Config(); GlobalVars.UserConfiguration.SelectedClient = GlobalVars.ProgramInformation.DefaultClient; GlobalVars.UserConfiguration.Map = GlobalVars.ProgramInformation.DefaultMap; @@ -1333,6 +1347,8 @@ public class FileManagement #if LAUNCHER GlobalVars.UserConfiguration.LauncherStyle = style; #endif + GlobalVars.UserConfiguration.WebProxyInitialSetupRequired = WebProxySetupComplete; + GlobalVars.UserConfiguration.WebProxyEnabled = WebProxy; NovetusFuncs.GeneratePlayerID(); ResetCustomizationValues(); } diff --git a/Novetus/NovetusCore/StorageAndFunctions/Util.cs b/Novetus/NovetusCore/StorageAndFunctions/Util.cs index 42911a7..73bb7cf 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/Util.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/Util.cs @@ -678,42 +678,6 @@ public static class Util return (p <= 0); } - private static void FormPrint(string text, int type, RichTextBox box, bool noTime = false) - { - if (box == null) - return; - - if (!noTime) - { - box.AppendText("[" + DateTime.Now.ToShortTimeString() + "] - ", Color.White); - } - - switch (type) - { - case 1: - box.AppendText(text, Color.White); - break; - case 2: - box.AppendText(text, Color.Red); - break; - case 3: - box.AppendText(text, Color.Lime); - break; - case 4: - box.AppendText(text, Color.Aqua); - break; - case 5: - box.AppendText(text, Color.Yellow); - break; - case 0: - default: - box.AppendText(text, Color.Black); - break; - } - - box.AppendText(Environment.NewLine, Color.White); - } - public static void ConsolePrint(string text, int type = 1, bool notime = false, bool noLog = false) { if (!notime) @@ -762,6 +726,75 @@ public static class Util #endif } + public static void ConsolePrintMultiLine(string text, int type = 1, bool notime = false, bool noLog = false) + { + try + { + string[] NewlineChars = {Environment.NewLine, "\n"}; + string[] lines = text.Split(NewlineChars, StringSplitOptions.None); + ConsolePrintMultiLine(lines, type, notime, noLog); + } + catch (Exception e) + { +#if URI || LAUNCHER || BASICLAUNCHER + LogExceptions(e); +#endif + } + } + + public static void ConsolePrintMultiLine(ICollection textColection, int type = 1, bool notime = false, bool noLog = false) + { + if (!textColection.Any()) + return; + + if (textColection.Count == 1) + { + ConsolePrint(textColection.First(), type, notime, noLog); + return; + } + + foreach (string text in textColection) + { + ConsolePrint(text, type, notime, noLog); + } + } + + private static void FormPrint(string text, int type, RichTextBox box, bool noTime = false) + { + if (box == null) + return; + + if (!noTime) + { + box.AppendText("[" + DateTime.Now.ToShortTimeString() + "] - ", Color.White); + } + + switch (type) + { + case 1: + box.AppendText(text, Color.White); + break; + case 2: + box.AppendText(text, Color.Red); + break; + case 3: + box.AppendText(text, Color.Lime); + break; + case 4: + box.AppendText(text, Color.Aqua); + break; + case 5: + box.AppendText(text, Color.Yellow); + break; + case 0: + default: + box.AppendText(text, Color.Black); + break; + } + + box.AppendText(Environment.NewLine, Color.White); + } + private static void ConsoleText(string text, ConsoleColor color, bool newLine = false) { Console.ForegroundColor = color; diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs index bab066e..7ca63ac 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs @@ -125,6 +125,8 @@ namespace NovetusLauncher { LocalVars.launcherInitState = false; } + + GlobalVars.Proxy.DoSetup(); } public string GetProductVersion() @@ -626,7 +628,7 @@ namespace NovetusLauncher Util.ConsolePrint("Config Saved.", 3); } - public void ResetConfigValues(bool ShowBox = false) + public void ResetConfigValuesInternal() { //https://stackoverflow.com/questions/9029351/close-all-open-forms-except-the-main-menu-in-c-sharp List
openForms = new List(); @@ -636,11 +638,19 @@ namespace NovetusLauncher foreach (Form f in openForms) { + if (f.GetType() == typeof(NovetusConsole)) + continue; + if (f.Name != Parent.Name) f.Close(); } FileManagement.ResetConfigValues(FormStyle); + } + + public void ResetConfigValues(bool ShowBox = false) + { + ResetConfigValuesInternal(); WriteConfigValues(); ReadConfigValues(); if (ShowBox) diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylish.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylish.cs index 6d0dcee..412afbc 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylish.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylish.cs @@ -156,19 +156,7 @@ namespace NovetusLauncher public void ResetConfigValues(bool ShowBox = false) { - //https://stackoverflow.com/questions/9029351/close-all-open-forms-except-the-main-menu-in-c-sharp - List openForms = new List(); - - foreach (Form f in Application.OpenForms) - openForms.Add(f); - - foreach (Form f in openForms) - { - if (f.Name != Name) - f.Close(); - } - - FileManagement.ResetConfigValues(Settings.Style.Stylish); + launcherFormStylishInterface1.launcherForm.ResetConfigValuesInternal(); WriteConfigValues(); ReadConfigValues(); if (ShowBox) diff --git a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs index bad4b05..57096aa 100644 --- a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs +++ b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs @@ -364,20 +364,71 @@ namespace NovetusLauncher if (vals[1].Equals("on", StringComparison.InvariantCultureIgnoreCase)) { + if (GlobalVars.Proxy.HasStarted()) + { + Util.ConsolePrint("The web proxy is already on and running.", 2); + return; + } + + if (GlobalVars.UserConfiguration.WebProxyInitialSetupRequired) + { + // this is wierd and really dumb if we are just using console mode..... + GlobalVars.Proxy.DoSetup(); + } + else + { + if (!GlobalVars.UserConfiguration.WebProxyEnabled) + { + GlobalVars.UserConfiguration.WebProxyEnabled = true; + } + } + GlobalVars.Proxy.Start(); } else if (vals[1].Equals("off", StringComparison.InvariantCultureIgnoreCase)) { + if (!GlobalVars.Proxy.HasStarted()) + { + Util.ConsolePrint("The web proxy is already turned off.", 2); + return; + } + + if (!GlobalVars.UserConfiguration.WebProxyEnabled) + { + Util.ConsolePrint("The web proxy is disabled. Please turn it on in order to use this command.", 2); + return; + } + GlobalVars.Proxy.Stop(); } + else if (vals[1].Equals("disable", StringComparison.InvariantCultureIgnoreCase)) + { + if (!GlobalVars.Proxy.HasStarted() && !GlobalVars.UserConfiguration.WebProxyEnabled) + { + Util.ConsolePrint("The web proxy is already disabled.", 2); + return; + } + + if (GlobalVars.UserConfiguration.WebProxyEnabled) + { + GlobalVars.UserConfiguration.WebProxyEnabled = false; + } + + if (GlobalVars.Proxy.HasStarted()) + { + GlobalVars.Proxy.Stop(); + } + + Util.ConsolePrint("The web proxy has been disabled. To re-enable it, use the 'proxy on' command.", 2); + } else { - Util.ConsolePrint("Please specify 'on' or 'off'.", 2); + Util.ConsolePrint("Please specify 'on', 'off', or 'disable'.", 2); } } catch (Exception) { - Util.ConsolePrint("Please specify 'on' or 'off'.", 2); + Util.ConsolePrint("Please specify 'on' or 'off', or 'disable'.", 2); } break; default: diff --git a/Novetus/NovetusURI/Forms/QuickConfigure.cs b/Novetus/NovetusURI/Forms/QuickConfigure.cs index d85a862..76ba01e 100644 --- a/Novetus/NovetusURI/Forms/QuickConfigure.cs +++ b/Novetus/NovetusURI/Forms/QuickConfigure.cs @@ -22,6 +22,7 @@ namespace NovetusURI { ReadConfigValues(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ConfigName); CenterToScreen(); + GlobalVars.Proxy.DoSetup(); } void Button3Click(object sender, EventArgs e) -- 2.40.1 From f46b7d9a9cebc07c96ee2e0dc28085402497d96d Mon Sep 17 00:00:00 2001 From: Bitl Date: Thu, 5 Jan 2023 10:07:51 -0700 Subject: [PATCH 13/85] add Novetus.Core namespace. Basic web proxy Extension support. --- Novetus/Novetus.Bootstrapper/LocalFuncs.cs | 1 + Novetus/Novetus.Bootstrapper/LocalPaths.cs | 1 + .../Novetus.Bootstrapper/NovetusLaunchForm.cs | 1 + .../CharacterCustomizationShared.cs | 1 + .../CharacterCustomizationCompact.Designer.cs | 2 + .../Compact/CharacterCustomizationCompact.cs | 1 + ...CharacterCustomizationExtended.Designer.cs | 2 + .../CharacterCustomizationExtended.cs | 1 + .../Classes/CommandLineArguments.cs | 5 +- Novetus/NovetusCore/Classes/CryptoRandom.cs | 77 +- Novetus/NovetusCore/Classes/Downloader.cs | 411 +-- Novetus/NovetusCore/Classes/IDiscordRPC.cs | 179 +- Novetus/NovetusCore/Classes/INIFile.cs | 137 +- Novetus/NovetusCore/Classes/Script.cs | 111 + .../NovetusCore/Classes/TextLineRemover.cs | 151 +- Novetus/NovetusCore/Classes/UHWIDEngine.cs | 3 +- Novetus/NovetusCore/Classes/WebProxy.cs | 358 ++- Novetus/NovetusCore/NovetusCore.projitems | 1 + .../StorageAndFunctions/ClientManagement.cs | 2805 +++++++++-------- .../StorageAndFunctions/FileManagement.cs | 2641 ++++++++-------- .../StorageAndFunctions/GlobalPaths.cs | 205 +- .../StorageAndFunctions/GlobalVars.cs | 221 +- .../StorageAndFunctions/NetFuncs.cs | 77 +- .../StorageAndFunctions/NovetusFuncs.cs | 1163 +++---- .../StorageAndFunctions/SecurityFuncs.cs | 647 ++-- .../NovetusCore/StorageAndFunctions/Util.cs | 1641 +++++----- .../Classes/Launcher/ModManager.cs | 1 + .../Classes/Launcher/SplashLoader.cs | 1 + .../Classes/Launcher/TreeNodeHelper.cs | 1 + .../Forms/CustomGraphicsOptions.cs | 1 + Novetus/NovetusLauncher/Forms/Decoder.cs | 3 +- .../Compact/LauncherFormCompact.Designer.cs | 2 + .../Compact/LauncherFormCompact.cs | 1 + .../Extended/LauncherFormExtended.Designer.cs | 2 + .../Extended/LauncherFormExtended.cs | 1 + .../Forms/LauncherForm/LauncherFormShared.cs | 1 + .../Stylish/LauncherFormStylish.cs | 1 + .../LauncherFormStylishInterface.xaml.cs | 1 + .../Forms/LauncherFormSettings.cs | 1 + .../NovetusLauncher/Forms/NovetusConsole.cs | 1 + .../Forms/SDK/AssetDownloader.cs | 1 + .../NovetusLauncher/Forms/SDK/AssetFixer.cs | 1 + .../Forms/SDK/ClientScriptDocumentation.cs | 3 +- .../Forms/SDK/ClientinfoCreator.cs | 1 + .../Forms/SDK/DiogenesEditor.cs | 1 + .../Forms/SDK/ItemCreationSDK.cs | 1 + .../Forms/SDK/ItemCreationSDKColorMenu.cs | 1 + .../Forms/SDK/MeshConverter.cs | 1 + .../NovetusLauncher/Forms/SDK/ModCreator.cs | 3 +- .../NovetusLauncher/Forms/SDK/NovetusSDK.cs | 1 + .../NovetusLauncher/Forms/SDK/SplashTester.cs | 1 + .../Forms/SDK/XMLContentEditor.cs | 1 + .../NovetusLauncher/Forms/ServerBrowser.cs | 1 + .../NovetusLauncherEntryPoint.cs | 1 + Novetus/NovetusURI/Classes/LocalFuncs.cs | 1 + Novetus/NovetusURI/Forms/InstallForm.cs | 1 + Novetus/NovetusURI/Forms/LoaderForm.cs | 1 + Novetus/NovetusURI/Forms/QuickConfigure.cs | 1 + Novetus/NovetusURI/NovetusURI.cs | 1 + 59 files changed, 5598 insertions(+), 5286 deletions(-) create mode 100644 Novetus/NovetusCore/Classes/Script.cs diff --git a/Novetus/Novetus.Bootstrapper/LocalFuncs.cs b/Novetus/Novetus.Bootstrapper/LocalFuncs.cs index 8d05d5b..abcfe85 100644 --- a/Novetus/Novetus.Bootstrapper/LocalFuncs.cs +++ b/Novetus/Novetus.Bootstrapper/LocalFuncs.cs @@ -1,5 +1,6 @@ #region Usings using NLog; +using Novetus.Core; using System; using System.Diagnostics; using System.IO; diff --git a/Novetus/Novetus.Bootstrapper/LocalPaths.cs b/Novetus/Novetus.Bootstrapper/LocalPaths.cs index 771e596..3005387 100644 --- a/Novetus/Novetus.Bootstrapper/LocalPaths.cs +++ b/Novetus/Novetus.Bootstrapper/LocalPaths.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System.IO; using System.Reflection; #endregion diff --git a/Novetus/Novetus.Bootstrapper/NovetusLaunchForm.cs b/Novetus/Novetus.Bootstrapper/NovetusLaunchForm.cs index 3c8e1bb..13c03be 100644 --- a/Novetus/Novetus.Bootstrapper/NovetusLaunchForm.cs +++ b/Novetus/Novetus.Bootstrapper/NovetusLaunchForm.cs @@ -1,4 +1,5 @@ using NLog; +using Novetus.Core; using System; using System.Drawing; using System.Drawing.Text; diff --git a/Novetus/NovetusCore/CharCustom/CharacterCustomizationShared.cs b/Novetus/NovetusCore/CharCustom/CharacterCustomizationShared.cs index f9680ff..a52f557 100644 --- a/Novetus/NovetusCore/CharCustom/CharacterCustomizationShared.cs +++ b/Novetus/NovetusCore/CharCustom/CharacterCustomizationShared.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/Novetus/NovetusCore/CharCustom/Forms/Compact/CharacterCustomizationCompact.Designer.cs b/Novetus/NovetusCore/CharCustom/Forms/Compact/CharacterCustomizationCompact.Designer.cs index ad9f23b..4f6685a 100644 --- a/Novetus/NovetusCore/CharCustom/Forms/Compact/CharacterCustomizationCompact.Designer.cs +++ b/Novetus/NovetusCore/CharCustom/Forms/Compact/CharacterCustomizationCompact.Designer.cs @@ -7,6 +7,8 @@ * To change this template use Tools | Options | Coding | Edit Standard Headers. */ +using Novetus.Core; + partial class CharacterCustomizationCompact { /// diff --git a/Novetus/NovetusCore/CharCustom/Forms/Compact/CharacterCustomizationCompact.cs b/Novetus/NovetusCore/CharCustom/Forms/Compact/CharacterCustomizationCompact.cs index 31293c8..5e57cba 100644 --- a/Novetus/NovetusCore/CharCustom/Forms/Compact/CharacterCustomizationCompact.cs +++ b/Novetus/NovetusCore/CharCustom/Forms/Compact/CharacterCustomizationCompact.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Collections.Generic; using System.ComponentModel; diff --git a/Novetus/NovetusCore/CharCustom/Forms/Extended/CharacterCustomizationExtended.Designer.cs b/Novetus/NovetusCore/CharCustom/Forms/Extended/CharacterCustomizationExtended.Designer.cs index c34e88f..31e009f 100644 --- a/Novetus/NovetusCore/CharCustom/Forms/Extended/CharacterCustomizationExtended.Designer.cs +++ b/Novetus/NovetusCore/CharCustom/Forms/Extended/CharacterCustomizationExtended.Designer.cs @@ -6,6 +6,8 @@ * * To change this template use Tools | Options | Coding | Edit Standard Headers. */ +using Novetus.Core; + partial class CharacterCustomizationExtended { /// diff --git a/Novetus/NovetusCore/CharCustom/Forms/Extended/CharacterCustomizationExtended.cs b/Novetus/NovetusCore/CharCustom/Forms/Extended/CharacterCustomizationExtended.cs index 0da8827..f802a87 100644 --- a/Novetus/NovetusCore/CharCustom/Forms/Extended/CharacterCustomizationExtended.cs +++ b/Novetus/NovetusCore/CharCustom/Forms/Extended/CharacterCustomizationExtended.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Collections.Generic; using System.ComponentModel; diff --git a/Novetus/NovetusCore/Classes/CommandLineArguments.cs b/Novetus/NovetusCore/Classes/CommandLineArguments.cs index d685e98..212b26c 100644 --- a/Novetus/NovetusCore/Classes/CommandLineArguments.cs +++ b/Novetus/NovetusCore/Classes/CommandLineArguments.cs @@ -3,7 +3,9 @@ using System.Collections.Specialized; using System.Text.RegularExpressions; #endregion -#region CommandLineArguments +namespace Novetus.Core +{ + #region CommandLineArguments public class CommandLineArguments { //https://www.codeproject.com/Articles/3111/C-NET-Command-Line-Arguments-Parser @@ -118,3 +120,4 @@ using System.Text.RegularExpressions; } } #endregion +} diff --git a/Novetus/NovetusCore/Classes/CryptoRandom.cs b/Novetus/NovetusCore/Classes/CryptoRandom.cs index ac252f3..2a879f0 100644 --- a/Novetus/NovetusCore/Classes/CryptoRandom.cs +++ b/Novetus/NovetusCore/Classes/CryptoRandom.cs @@ -3,49 +3,52 @@ using System; using System.Security.Cryptography; #endregion -#region CryptoRandom - -public class CryptoRandom : RandomNumberGenerator +namespace Novetus.Core { - private static RandomNumberGenerator r; + #region CryptoRandom - public CryptoRandom() + public class CryptoRandom : RandomNumberGenerator { - r = Create(); - } + private static RandomNumberGenerator r; - ///An array of bytes to contain random numbers. - public override void GetBytes(byte[] buffer) - { - r.GetBytes(buffer); - } + public CryptoRandom() + { + r = Create(); + } - public override void GetNonZeroBytes(byte[] data) - { - r.GetNonZeroBytes(data); - } - public double NextDouble() - { - byte[] b = new byte[4]; - r.GetBytes(b); - return (double)BitConverter.ToUInt32(b, 0) / UInt32.MaxValue; - } + ///An array of bytes to contain random numbers. + public override void GetBytes(byte[] buffer) + { + r.GetBytes(buffer); + } - ///The inclusive lower bound of the random number returned. - ///The exclusive upper bound of the random number returned. maxValue must be greater than or equal to minValue. - public int Next(int minValue, int maxValue) - { - return (int)Math.Round(NextDouble() * (maxValue - minValue - 1)) + minValue; - } - public int Next() - { - return Next(0, int.MaxValue); - } + public override void GetNonZeroBytes(byte[] data) + { + r.GetNonZeroBytes(data); + } + public double NextDouble() + { + byte[] b = new byte[4]; + r.GetBytes(b); + return (double)BitConverter.ToUInt32(b, 0) / UInt32.MaxValue; + } - ///The inclusive upper bound of the random number returned. maxValue must be greater than or equal 0 - public int Next(int maxValue) - { - return Next(0, maxValue); + ///The inclusive lower bound of the random number returned. + ///The exclusive upper bound of the random number returned. maxValue must be greater than or equal to minValue. + public int Next(int minValue, int maxValue) + { + return (int)Math.Round(NextDouble() * (maxValue - minValue - 1)) + minValue; + } + public int Next() + { + return Next(0, int.MaxValue); + } + + ///The inclusive upper bound of the random number returned. maxValue must be greater than or equal 0 + public int Next(int maxValue) + { + return Next(0, maxValue); + } } + #endregion } -#endregion diff --git a/Novetus/NovetusCore/Classes/Downloader.cs b/Novetus/NovetusCore/Classes/Downloader.cs index c9f9b44..225e9f0 100644 --- a/Novetus/NovetusCore/Classes/Downloader.cs +++ b/Novetus/NovetusCore/Classes/Downloader.cs @@ -6,245 +6,248 @@ using System.Threading; using System.Windows.Forms; #endregion -#region Downloader - -class Downloader +namespace Novetus.Core { - public readonly string fileURL; - public readonly string fileName; - public readonly string fileFilter; - public readonly string filePath; - public static bool showErrorInfo = true; - public static bool overwrite = true; - public int downloadSize; - private string downloadOutcome; - private static string downloadOutcomeException; + #region Downloader - public Downloader(string url, string name, string filter) + class Downloader { - fileName = name; - fileURL = url; - fileFilter = filter; - } + public readonly string fileURL; + public readonly string fileName; + public readonly string fileFilter; + public readonly string filePath; + public static bool showErrorInfo = true; + public static bool overwrite = true; + public int downloadSize; + private string downloadOutcome; + private static string downloadOutcomeException; - public Downloader(string url, string name, string filter, string path) - { - fileName = name; - fileURL = url; - fileFilter = filter; - filePath = path; - } - - public Downloader(string url, string name) - { - fileName = name; - fileURL = url; - fileFilter = ""; - } - - public void setDownloadOptions(bool ExtraErrorInfo, bool OverwriteFiles) - { - showErrorInfo = ExtraErrorInfo; - overwrite = OverwriteFiles; - } - - public string getDownloadOutcome() - { - return downloadOutcome; - } - - public void InitDownloadDirect(string path, string fileext, string additionalText = "", bool removeSpaces = false) - { - string outputfilename = ""; - - if (removeSpaces == true) + public Downloader(string url, string name, string filter) { - outputfilename = (fileName + fileext).Replace(" ", ""); - } - else - { - outputfilename = fileName + fileext; - } - - string fullpath = path + "\\" + outputfilename; - - InitDownloadNoDialog(fullpath, additionalText); - } - - public void InitDownload(string additionalText = "") - { - SaveFileDialog saveFileDialog1 = new SaveFileDialog - { - FileName = fileName, - //"Compressed zip files (*.zip)|*.zip|All files (*.*)|*.*" - Filter = fileFilter, - Title = "Save " + fileName - }; - - if (saveFileDialog1.ShowDialog() == DialogResult.OK) - { - InitDownloadNoDialog(saveFileDialog1.FileName, additionalText); - } - } - - public void InitDownloadNoDialog(string name, string additionalText = "") - { - if (!overwrite && File.Exists(name)) - { - downloadOutcome = "Download skipped due to same file name."; - return; + fileName = name; + fileURL = url; + fileFilter = filter; } - int read = 0; - - try + public Downloader(string url, string name, string filter, string path) { - read = DownloadFile(fileURL, name); + fileName = name; + fileURL = url; + fileFilter = filter; + filePath = path; } + + public Downloader(string url, string name) + { + fileName = name; + fileURL = url; + fileFilter = ""; + } + + public void setDownloadOptions(bool ExtraErrorInfo, bool OverwriteFiles) + { + showErrorInfo = ExtraErrorInfo; + overwrite = OverwriteFiles; + } + + public string getDownloadOutcome() + { + return downloadOutcome; + } + + public void InitDownloadDirect(string path, string fileext, string additionalText = "", bool removeSpaces = false) + { + string outputfilename = ""; + + if (removeSpaces == true) + { + outputfilename = (fileName + fileext).Replace(" ", ""); + } + else + { + outputfilename = fileName + fileext; + } + + string fullpath = path + "\\" + outputfilename; + + InitDownloadNoDialog(fullpath, additionalText); + } + + public void InitDownload(string additionalText = "") + { + SaveFileDialog saveFileDialog1 = new SaveFileDialog + { + FileName = fileName, + //"Compressed zip files (*.zip)|*.zip|All files (*.*)|*.*" + Filter = fileFilter, + Title = "Save " + fileName + }; + + if (saveFileDialog1.ShowDialog() == DialogResult.OK) + { + InitDownloadNoDialog(saveFileDialog1.FileName, additionalText); + } + } + + public void InitDownloadNoDialog(string name, string additionalText = "") + { + if (!overwrite && File.Exists(name)) + { + downloadOutcome = "Download skipped due to same file name."; + return; + } + + int read = 0; + + try + { + read = DownloadFile(fileURL, name); + } #if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); + catch (Exception ex) + { + Util.LogExceptions(ex); #else catch (Exception) { #endif - downloadOutcome = "Error when downloading file: " + ex.Message; - } - finally - { - //wait a few seconds for the download to finish - //Thread.Sleep(2000); - if (File.Exists(name) && read > 0) - { - downloadSize = read; - downloadOutcome = "File " + Path.GetFileName(name) + " downloaded! " + Util.SizeSuffix(Convert.ToInt64(downloadSize), 2) + " written (" + downloadSize + " bytes)! " + additionalText; + downloadOutcome = "Error when downloading file: " + ex.Message; } - else + finally { - if (!string.IsNullOrWhiteSpace(downloadOutcomeException)) + //wait a few seconds for the download to finish + //Thread.Sleep(2000); + if (File.Exists(name) && read > 0) { - downloadOutcome = "Error: Download of file " + Path.GetFileName(name) + " failed. " + downloadOutcomeException; + downloadSize = read; + downloadOutcome = "File " + Path.GetFileName(name) + " downloaded! " + Util.SizeSuffix(Convert.ToInt64(downloadSize), 2) + " written (" + downloadSize + " bytes)! " + additionalText; } else { - downloadOutcome = "Error: Download of file " + Path.GetFileName(name) + " failed. The file wasn't downloaded to the assigned directory."; - } - - if (showErrorInfo) - { - downloadOutcome += "\n\nMore error info:\n\nFile URL: " + fileURL + "\n\nFile Path: " + name; - } - } - } - } - - public string GetFullDLPath() - { - return filePath + Path.DirectorySeparatorChar + fileName; - } - - private static int DownloadFile(string remoteFilename, string localFilename) - { - //credit to Tom Archer (https://www.codeguru.com/columns/dotnettips/article.php/c7005/Downloading-Files-with-the-WebRequest-and-WebResponse-Classes.htm) - //and Brokenglass (https://stackoverflow.com/questions/4567313/uncompressing-gzip-response-from-webclient/4567408#4567408) - - // Function will return the number of bytes processed - // to the caller. Initialize to 0 here. - int bytesProcessed = 0; - - // Assign values to these objects here so that they can - // be referenced in the finally block - Stream remoteStream = null; - Stream localStream = null; - WebResponse response = null; - - // Use a try/catch/finally block as both the WebRequest and Stream - // classes throw exceptions upon error - //thanks to https://stackoverflow.com/questions/33761919/tls-1-2-in-net-framework-4-0 for the net 4.0 compatible TLS 1.1/1.2 code! - try - { - ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls - | (SecurityProtocolType)3072 - | (SecurityProtocolType)768 - | SecurityProtocolType.Ssl3; - ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true; - // Create a request for the specified remote file name - HttpWebRequest request = (HttpWebRequest)WebRequest.Create(remoteFilename); - //changing it to just "roblox" since roblox is breaking everything. - //request.UserAgent = "Roblox/WinINet"; - request.UserAgent = "Roblox"; - request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate"); - request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; - if (request != null) - { - // Send the request to the server and retrieve the - // WebResponse object - response = request.GetResponse(); - if (response != null) - { - // Once the WebResponse object has been retrieved, - // get the stream object associated with the response's data - remoteStream = response.GetResponseStream(); - - // Create the local file - localStream = File.Create(localFilename); - - // Allocate a 1k buffer - byte[] buffer = new byte[1024]; - int bytesRead; - - // Simple do/while loop to read from stream until - // no bytes are returned - do + if (!string.IsNullOrWhiteSpace(downloadOutcomeException)) { - // Read data (up to 1k) from the stream - bytesRead = remoteStream.Read(buffer, 0, buffer.Length); + downloadOutcome = "Error: Download of file " + Path.GetFileName(name) + " failed. " + downloadOutcomeException; + } + else + { + downloadOutcome = "Error: Download of file " + Path.GetFileName(name) + " failed. The file wasn't downloaded to the assigned directory."; + } - // Write the data to the local file - localStream.Write(buffer, 0, bytesRead); - - // Increment total bytes processed - bytesProcessed += bytesRead; - } while (bytesRead > 0); + if (showErrorInfo) + { + downloadOutcome += "\n\nMore error info:\n\nFile URL: " + fileURL + "\n\nFile Path: " + name; + } } } } - catch (Exception e) + + public string GetFullDLPath() { -#if URI || LAUNCHER || BASICLAUNCHER - Util.LogExceptions(e); -#endif - if (e is WebException && bytesProcessed == 0) + return filePath + Path.DirectorySeparatorChar + fileName; + } + + private static int DownloadFile(string remoteFilename, string localFilename) + { + //credit to Tom Archer (https://www.codeguru.com/columns/dotnettips/article.php/c7005/Downloading-Files-with-the-WebRequest-and-WebResponse-Classes.htm) + //and Brokenglass (https://stackoverflow.com/questions/4567313/uncompressing-gzip-response-from-webclient/4567408#4567408) + + // Function will return the number of bytes processed + // to the caller. Initialize to 0 here. + int bytesProcessed = 0; + + // Assign values to these objects here so that they can + // be referenced in the finally block + Stream remoteStream = null; + Stream localStream = null; + WebResponse response = null; + + // Use a try/catch/finally block as both the WebRequest and Stream + // classes throw exceptions upon error + //thanks to https://stackoverflow.com/questions/33761919/tls-1-2-in-net-framework-4-0 for the net 4.0 compatible TLS 1.1/1.2 code! + try { - WebException ex = (WebException)e; - HttpWebResponse errorResponse = ex.Response as HttpWebResponse; - if (errorResponse.StatusCode == HttpStatusCode.Conflict || errorResponse.StatusCode == HttpStatusCode.Forbidden) + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls + | (SecurityProtocolType)3072 + | (SecurityProtocolType)768 + | SecurityProtocolType.Ssl3; + ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true; + // Create a request for the specified remote file name + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(remoteFilename); + //changing it to just "roblox" since roblox is breaking everything. + //request.UserAgent = "Roblox/WinINet"; + request.UserAgent = "Roblox"; + request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate"); + request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + if (request != null) { - downloadOutcomeException = "Error: Unable to download item. The item may not be publically available."; + // Send the request to the server and retrieve the + // WebResponse object + response = request.GetResponse(); + if (response != null) + { + // Once the WebResponse object has been retrieved, + // get the stream object associated with the response's data + remoteStream = response.GetResponseStream(); + + // Create the local file + localStream = File.Create(localFilename); + + // Allocate a 1k buffer + byte[] buffer = new byte[1024]; + int bytesRead; + + // Simple do/while loop to read from stream until + // no bytes are returned + do + { + // Read data (up to 1k) from the stream + bytesRead = remoteStream.Read(buffer, 0, buffer.Length); + + // Write the data to the local file + localStream.Write(buffer, 0, bytesRead); + + // Increment total bytes processed + bytesProcessed += bytesRead; + } while (bytesRead > 0); + } + } + } + catch (Exception e) + { +#if URI || LAUNCHER || BASICLAUNCHER + Util.LogExceptions(e); +#endif + if (e is WebException && bytesProcessed == 0) + { + WebException ex = (WebException)e; + HttpWebResponse errorResponse = ex.Response as HttpWebResponse; + if (errorResponse.StatusCode == HttpStatusCode.Conflict || errorResponse.StatusCode == HttpStatusCode.Forbidden) + { + downloadOutcomeException = "Error: Unable to download item. The item may not be publically available."; + } + else + { + downloadOutcomeException = "Exception: " + ex.Message; + } } else { - downloadOutcomeException = "Exception: " + ex.Message; + downloadOutcomeException = "Exception: " + e.Message; } } - else + finally { - downloadOutcomeException = "Exception: " + e.Message; + // Close the response and streams objects here + // to make sure they're closed even if an exception + // is thrown at some point + if (response != null) response.Close(); + if (remoteStream != null) remoteStream.Close(); + if (localStream != null) localStream.Close(); } - } - finally - { - // Close the response and streams objects here - // to make sure they're closed even if an exception - // is thrown at some point - if (response != null) response.Close(); - if (remoteStream != null) remoteStream.Close(); - if (localStream != null) localStream.Close(); - } - // Return total bytes processed to caller. - return bytesProcessed; + // Return total bytes processed to caller. + return bytesProcessed; + } } + #endregion } -#endregion diff --git a/Novetus/NovetusCore/Classes/IDiscordRPC.cs b/Novetus/NovetusCore/Classes/IDiscordRPC.cs index 0899dc9..afda33f 100644 --- a/Novetus/NovetusCore/Classes/IDiscordRPC.cs +++ b/Novetus/NovetusCore/Classes/IDiscordRPC.cs @@ -2,95 +2,98 @@ using System.Runtime.InteropServices; #endregion -#region Discord RPC -//code by discord obv. just renamed it to fit better. -public class DiscordRPC +namespace Novetus.Core { - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void ReadyCallback(); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void DisconnectedCallback(int errorCode, string message); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void ErrorCallback(int errorCode, string message); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void JoinCallback(string secret); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void SpectateCallback(string secret); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void RequestCallback(JoinRequest request); - - public struct EventHandlers + #region Discord RPC + //code by discord obv. just renamed it to fit better. + public class DiscordRPC { - public ReadyCallback readyCallback; - public DisconnectedCallback disconnectedCallback; - public ErrorCallback errorCallback; - public JoinCallback joinCallback; - public SpectateCallback spectateCallback; - public RequestCallback requestCallback; + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void ReadyCallback(); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void DisconnectedCallback(int errorCode, string message); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void ErrorCallback(int errorCode, string message); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void JoinCallback(string secret); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void SpectateCallback(string secret); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void RequestCallback(JoinRequest request); + + public struct EventHandlers + { + public ReadyCallback readyCallback; + public DisconnectedCallback disconnectedCallback; + public ErrorCallback errorCallback; + public JoinCallback joinCallback; + public SpectateCallback spectateCallback; + public RequestCallback requestCallback; + } + + [System.Serializable] + public struct RichPresence + { + public string state; + /* max 128 bytes */ + public string details; + /* max 128 bytes */ + public long startTimestamp; + public long endTimestamp; + public string largeImageKey; + /* max 32 bytes */ + public string largeImageText; + /* max 128 bytes */ + public string smallImageKey; + /* max 32 bytes */ + public string smallImageText; + /* max 128 bytes */ + public string partyId; + /* max 128 bytes */ + public int partySize; + public int partyMax; + public string matchSecret; + /* max 128 bytes */ + public string joinSecret; + /* max 128 bytes */ + public string spectateSecret; + /* max 128 bytes */ + public bool instance; + } + + [System.Serializable] + public struct JoinRequest + { + public string userId; + public string username; + public string avatar; + } + + public enum Reply + { + No = 0, + Yes = 1, + Ignore = 2 + } + [DllImport("discord-rpc", EntryPoint = "Discord_Initialize", CallingConvention = CallingConvention.Cdecl)] + public static extern void Initialize(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId); + + [DllImport("discord-rpc", EntryPoint = "Discord_Shutdown", CallingConvention = CallingConvention.Cdecl)] + public static extern void Shutdown(); + + [DllImport("discord-rpc", EntryPoint = "Discord_RunCallbacks", CallingConvention = CallingConvention.Cdecl)] + public static extern void RunCallbacks(); + + [DllImport("discord-rpc", EntryPoint = "Discord_UpdatePresence", CallingConvention = CallingConvention.Cdecl)] + public static extern void UpdatePresence(ref RichPresence presence); + + [DllImport("discord-rpc", EntryPoint = "Discord_Respond", CallingConvention = CallingConvention.Cdecl)] + public static extern void Respond(string userId, Reply reply); } - - [System.Serializable] - public struct RichPresence - { - public string state; - /* max 128 bytes */ - public string details; - /* max 128 bytes */ - public long startTimestamp; - public long endTimestamp; - public string largeImageKey; - /* max 32 bytes */ - public string largeImageText; - /* max 128 bytes */ - public string smallImageKey; - /* max 32 bytes */ - public string smallImageText; - /* max 128 bytes */ - public string partyId; - /* max 128 bytes */ - public int partySize; - public int partyMax; - public string matchSecret; - /* max 128 bytes */ - public string joinSecret; - /* max 128 bytes */ - public string spectateSecret; - /* max 128 bytes */ - public bool instance; - } - - [System.Serializable] - public struct JoinRequest - { - public string userId; - public string username; - public string avatar; - } - - public enum Reply - { - No = 0, - Yes = 1, - Ignore = 2 - } - [DllImport("discord-rpc", EntryPoint = "Discord_Initialize", CallingConvention = CallingConvention.Cdecl)] - public static extern void Initialize(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId); - - [DllImport("discord-rpc", EntryPoint = "Discord_Shutdown", CallingConvention = CallingConvention.Cdecl)] - public static extern void Shutdown(); - - [DllImport("discord-rpc", EntryPoint = "Discord_RunCallbacks", CallingConvention = CallingConvention.Cdecl)] - public static extern void RunCallbacks(); - - [DllImport("discord-rpc", EntryPoint = "Discord_UpdatePresence", CallingConvention = CallingConvention.Cdecl)] - public static extern void UpdatePresence(ref RichPresence presence); - - [DllImport("discord-rpc", EntryPoint = "Discord_Respond", CallingConvention = CallingConvention.Cdecl)] - public static extern void Respond(string userId, Reply reply); + #endregion } -#endregion diff --git a/Novetus/NovetusCore/Classes/INIFile.cs b/Novetus/NovetusCore/Classes/INIFile.cs index 9d944c0..3e4236c 100644 --- a/Novetus/NovetusCore/Classes/INIFile.cs +++ b/Novetus/NovetusCore/Classes/INIFile.cs @@ -5,95 +5,98 @@ using System.Runtime.InteropServices; using System.Text; #endregion -#region INI File Parser -//modified from https://www.codeproject.com/articles/1966/an-ini-file-handling-class-using-c?fid=425860&df=90&mpp=25&prof=True&sort=Position&view=Normal&spc=Relaxed&fr=51 - -public class INIFile +namespace Novetus.Core { - public string path; + #region INI File Parser + //modified from https://www.codeproject.com/articles/1966/an-ini-file-handling-class-using-c?fid=425860&df=90&mpp=25&prof=True&sort=Position&view=Normal&spc=Relaxed&fr=51 - [DllImport("kernel32")] - private static extern long WritePrivateProfileString(string section, - string key, string val, string filePath); - [DllImport("kernel32")] - private static extern int GetPrivateProfileString(string section, - string key, string def, StringBuilder retVal, - int size, string filePath); + public class INIFile + { + public string path; - /// - /// INIFile Constructor. - /// - /// - public INIFile(string INIPath) - { - path = INIPath; - } - /// - /// Write Data to the INI File - /// - /// - /// Section name - /// - /// Key Name - /// - /// Value Name - public void IniWriteValue(string Section, string Key, string Value) - { - WritePrivateProfileString(Section, Key, Value, path); - } + [DllImport("kernel32")] + private static extern long WritePrivateProfileString(string section, + string key, string val, string filePath); + [DllImport("kernel32")] + private static extern int GetPrivateProfileString(string section, + string key, string def, StringBuilder retVal, + int size, string filePath); - /// - /// Read Data Value From the Ini File - /// - /// - /// - /// - /// - public string IniReadValue(string Section, string Key, string DefaultValue = "") - { - if (IniValueExists(Key)) + /// + /// INIFile Constructor. + /// + /// + public INIFile(string INIPath) { - StringBuilder temp = new StringBuilder(255); - int i = GetPrivateProfileString(Section, Key, "", temp, - 255, path); - return temp.ToString(); + path = INIPath; } - else + /// + /// Write Data to the INI File + /// + /// + /// Section name + /// + /// Key Name + /// + /// Value Name + public void IniWriteValue(string Section, string Key, string Value) { - IniWriteValue(Section, Key, DefaultValue); - return DefaultValue; + WritePrivateProfileString(Section, Key, Value, path); } - } - public bool IniValueExists(string SearchString) - { - try + /// + /// Read Data Value From the Ini File + /// + /// + /// + /// + /// + public string IniReadValue(string Section, string Key, string DefaultValue = "") { - if (File.Exists(path)) + if (IniValueExists(Key)) { - string[] lines = File.ReadAllLines(path); + StringBuilder temp = new StringBuilder(255); + int i = GetPrivateProfileString(Section, Key, "", temp, + 255, path); + return temp.ToString(); + } + else + { + IniWriteValue(Section, Key, DefaultValue); + return DefaultValue; + } + } - foreach (string line in lines) + public bool IniValueExists(string SearchString) + { + try + { + if (File.Exists(path)) { - if (line.Contains(SearchString)) + string[] lines = File.ReadAllLines(path); + + foreach (string line in lines) { - return true; + if (line.Contains(SearchString)) + { + return true; + } } } - } - return false; - } + return false; + } #if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); + catch (Exception ex) + { + Util.LogExceptions(ex); #else catch (Exception) { #endif - return false; + return false; + } } } + #endregion } -#endregion diff --git a/Novetus/NovetusCore/Classes/Script.cs b/Novetus/NovetusCore/Classes/Script.cs new file mode 100644 index 0000000..d8b9525 --- /dev/null +++ b/Novetus/NovetusCore/Classes/Script.cs @@ -0,0 +1,111 @@ +#region Usings +using System; +using System.Reflection; +using Microsoft.CSharp; +using System.CodeDom.Compiler; +using System.IO; +using System.Linq; +#endregion + +// based on https://stackoverflow.com/questions/137933/what-is-the-best-scripting-language-to-embed-in-a-c-sharp-desktop-application +namespace Novetus.Core +{ + #region Script + public class Script + { + public static object LoadScriptFromContent(string scriptPath) + { + try + { + using (var stream = File.OpenRead(scriptPath)) + { + using (var reader = new StreamReader(stream)) + { + string script = reader.ReadToEnd(); + Assembly compiled = CompileScript(script, scriptPath); + object code = ExecuteScript(compiled, scriptPath); + return code; + } + } + } + catch (Exception ex) + { + ErrorHandler(scriptPath + ": " + ex.ToString(), true); + } + + return null; + } + + private static object ExecuteScript(Assembly assemblyScript, string filePath) + { + if (assemblyScript == null) + { + goto error; + } + + foreach (Type type in assemblyScript.GetExportedTypes()) + { + if (type.IsInterface || type.IsAbstract) + continue; + + ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes); + + if (constructor != null && constructor.IsPublic) + { + return constructor.Invoke(null); + } + else + { + ErrorHandler(filePath + ": Constructor does not exist or it is not public.", true); + return null; + } + } + +error: + ErrorHandler(filePath + ": Failed to load script.", true); + return null; + } + + private static Assembly CompileScript(string code, string filePath) + { + CSharpCodeProvider provider = new CSharpCodeProvider(); + + CompilerParameters perams = new CompilerParameters(); + perams.GenerateExecutable = false; + perams.GenerateInMemory = true; + + var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(a => !a.IsDynamic).Select(a => a.Location); + perams.ReferencedAssemblies.AddRange(assemblies.ToArray()); + + CompilerResults result = provider.CompileAssemblyFromSource(perams, code); + + foreach (CompilerError error in result.Errors) + { + ErrorHandler(error, filePath, error.IsWarning, false); + } + + if (result.Errors.HasErrors) + { + return null; + } + + return result.CompiledAssembly; + } + + public static void ErrorHandler(string error, bool finalError = false) + { + ErrorHandler(error, false, finalError); + } + + private static void ErrorHandler(string error, bool warning, bool finalError) + { + Util.ConsolePrint(warning ? "[SCRIPT WARNING] - " : "[SCRIPT ERROR] - " + error, warning ? 5 : 2); + } + + private static void ErrorHandler(CompilerError error, string fileName, bool warning, bool finalError) + { + Util.ConsolePrint(warning ? "[SCRIPT WARNING] - " : "[SCRIPT ERROR] - " + fileName + " (" + error.Line + "," + error.Column + "): " + error.ErrorText, warning ? 5 : 2); + } + } + #endregion +} diff --git a/Novetus/NovetusCore/Classes/TextLineRemover.cs b/Novetus/NovetusCore/Classes/TextLineRemover.cs index 2a44ee3..fe6d400 100644 --- a/Novetus/NovetusCore/Classes/TextLineRemover.cs +++ b/Novetus/NovetusCore/Classes/TextLineRemover.cs @@ -4,100 +4,103 @@ using System.Collections.Generic; using System.IO; #endregion -#region Text Line Remover and Friends -// modified from https://stackoverflow.com/questions/668907/how-to-delete-a-line-from-a-text-file-in-c/668914#668914 - -public static class TextLineRemover +namespace Novetus.Core { - public static void RemoveTextLines(IList linesToRemove, string filename, string tempFilename) - { - // Initial values - int lineNumber = 0; - int linesRemoved = 0; - DateTime startTime = DateTime.Now; + #region Text Line Remover and Friends + // modified from https://stackoverflow.com/questions/668907/how-to-delete-a-line-from-a-text-file-in-c/668914#668914 - // Read file - using (var sr = new StreamReader(filename)) + public static class TextLineRemover + { + public static void RemoveTextLines(IList linesToRemove, string filename, string tempFilename) { - // Write new file - using (var sw = new StreamWriter(tempFilename)) + // Initial values + int lineNumber = 0; + int linesRemoved = 0; + DateTime startTime = DateTime.Now; + + // Read file + using (var sr = new StreamReader(filename)) { - // Read lines - string line; - while ((line = sr.ReadLine()) != null) + // Write new file + using (var sw = new StreamWriter(tempFilename)) { - lineNumber++; - // Look for text to remove - if (!ContainsString(line, linesToRemove)) + // Read lines + string line; + while ((line = sr.ReadLine()) != null) { - // Keep lines that does not match - sw.WriteLine(line); - } - else - { - // Ignore lines that DO match - linesRemoved++; - InvokeOnRemovedLine(new RemovedLineArgs + lineNumber++; + // Look for text to remove + if (!ContainsString(line, linesToRemove)) { - RemovedLine = line, - RemovedLineNumber = lineNumber - }); + // Keep lines that does not match + sw.WriteLine(line); + } + else + { + // Ignore lines that DO match + linesRemoved++; + InvokeOnRemovedLine(new RemovedLineArgs + { + RemovedLine = line, + RemovedLineNumber = lineNumber + }); + } } } } + + //FixedFileMove deletes the original file and moves the temp file in. + Util.FixedFileMove(tempFilename, filename, true); + + // Final calculations + DateTime endTime = DateTime.Now; + InvokeOnFinished(new FinishedArgs + { + LinesRemoved = linesRemoved, + TotalLines = lineNumber, + TotalTime = endTime.Subtract(startTime) + }); } - //FixedFileMove deletes the original file and moves the temp file in. - Util.FixedFileMove(tempFilename, filename, true); - - // Final calculations - DateTime endTime = DateTime.Now; - InvokeOnFinished(new FinishedArgs + private static bool ContainsString(string line, IEnumerable linesToRemove) { - LinesRemoved = linesRemoved, - TotalLines = lineNumber, - TotalTime = endTime.Subtract(startTime) - }); - } - - private static bool ContainsString(string line, IEnumerable linesToRemove) - { - foreach (var lineToRemove in linesToRemove) - { - if (line.Contains(lineToRemove)) - return true; + foreach (var lineToRemove in linesToRemove) + { + if (line.Contains(lineToRemove)) + return true; + } + return false; + } + + public static event RemovedLine OnRemovedLine; + public static event Finished OnFinished; + + public static void InvokeOnFinished(FinishedArgs args) + { + OnFinished?.Invoke(null, args); + } + + public static void InvokeOnRemovedLine(RemovedLineArgs args) + { + OnRemovedLine?.Invoke(null, args); } - return false; } - public static event RemovedLine OnRemovedLine; - public static event Finished OnFinished; + public delegate void Finished(object sender, FinishedArgs args); - public static void InvokeOnFinished(FinishedArgs args) + public struct FinishedArgs { - OnFinished?.Invoke(null, args); + public int TotalLines { get; set; } + public int LinesRemoved { get; set; } + public TimeSpan TotalTime { get; set; } } - public static void InvokeOnRemovedLine(RemovedLineArgs args) + public delegate void RemovedLine(object sender, RemovedLineArgs args); + + public struct RemovedLineArgs { - OnRemovedLine?.Invoke(null, args); + public string RemovedLine { get; set; } + public int RemovedLineNumber { get; set; } } + #endregion } - -public delegate void Finished(object sender, FinishedArgs args); - -public struct FinishedArgs -{ - public int TotalLines { get; set; } - public int LinesRemoved { get; set; } - public TimeSpan TotalTime { get; set; } -} - -public delegate void RemovedLine(object sender, RemovedLineArgs args); - -public struct RemovedLineArgs -{ - public string RemovedLine { get; set; } - public int RemovedLineNumber { get; set; } -} -#endregion diff --git a/Novetus/NovetusCore/Classes/UHWIDEngine.cs b/Novetus/NovetusCore/Classes/UHWIDEngine.cs index 1821c7b..205586c 100644 --- a/Novetus/NovetusCore/Classes/UHWIDEngine.cs +++ b/Novetus/NovetusCore/Classes/UHWIDEngine.cs @@ -7,9 +7,10 @@ using System.IO; using System.Runtime.InteropServices; #endregion + //https://github.com/davcs86/csharp-uhwid //merged into one class -namespace UHWID +namespace Novetus.Core { #region UHWIDEngine public static class UHWIDEngine diff --git a/Novetus/NovetusCore/Classes/WebProxy.cs b/Novetus/NovetusCore/Classes/WebProxy.cs index a54446d..31892b3 100644 --- a/Novetus/NovetusCore/Classes/WebProxy.cs +++ b/Novetus/NovetusCore/Classes/WebProxy.cs @@ -12,162 +12,268 @@ using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Models; -public class WebProxy +namespace Novetus.Core { - private static ProxyServer Server = new ProxyServer(); - private static ExplicitProxyEndPoint end; - - public bool HasStarted() + public class IWebProxyExtension { - return Server.ProxyRunning; + public virtual string Name { get; set; } = "Unnamed Web Proxy Extension"; + public virtual void OnExtensionLoad() { } + public virtual void OnProxyStart() { } + public virtual void OnProxyStopped() { } + + public virtual bool IsValidURL(string absolutePath, string host) { return false; } + + public virtual Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) { return Task.CompletedTask; } +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + public virtual async Task OnRequest(object sender, SessionEventArgs e) { } +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously } - public void DoSetup() + public class WebProxy { - if (GlobalVars.UserConfiguration.WebProxyInitialSetupRequired) + private static List ExtensionList = new List(); + private static ProxyServer Server = new ProxyServer(); + private static ExplicitProxyEndPoint end; + + public void LoadExtensions() { - string text = "Would you like to enable the Novetus web proxy?\n\n" + - "A web proxy redirects web traffic to a different location and in some cases can act as a gateway to different sites. Novetus uses the web proxy for additional client features and asset redirection.\n\n" + - "When enabling the web proxy, Novetus will locally create a certificate upon startup that ensures the proxy's functionality. Novetus will not send any user data to anyone, as everything involving the web proxy is entirely local to this computer.\n" + - "If you have any issue connecting to other web sites, including Roblox, closing Novetus or typing 'proxy off' into Novetus' console will fix it in most instances.\n\n" + - "Upon pressing 'Yes', Windows will ask you for permission to install the certificate.\n\n" + - "You can change this option at any time by typing 'proxy disable' or 'proxy on' in the Novetus console. This message will appear only once.\n"; + string nothingFoundError = "No extensions found. The Web Proxy will run with limited functionality."; - DialogResult result = MessageBox.Show(text, "Novetus - Web Proxy Opt-In", MessageBoxButtons.YesNo); - - switch (result) + if (!Directory.Exists(GlobalPaths.NovetusExtsWebProxy)) { - case DialogResult.Yes: - GlobalVars.UserConfiguration.WebProxyEnabled = true; + Util.ConsolePrint(nothingFoundError, 5); + return; + } + + // load up all .cs files. + string[] filePaths = Directory.GetFiles(GlobalPaths.NovetusExtsWebProxy, "*.cs", SearchOption.TopDirectoryOnly); + + if (filePaths.Count() == 0) + { + Util.ConsolePrint(nothingFoundError, 5); + return; + } + + foreach (string file in filePaths) + { + try + { + IWebProxyExtension newExt = (IWebProxyExtension)Script.LoadScriptFromContent(file); + ExtensionList.Add(newExt); + Util.ConsolePrint("Web Proxy: Loaded extension " + newExt.Name + " from " + Path.GetFileName(file), 3); + newExt.OnExtensionLoad(); + } + catch (Exception e) + { + Util.LogExceptions(e); + } + } + } + + public bool HasStarted() + { + return Server.ProxyRunning; + } + + public void DoSetup() + { + if (GlobalVars.UserConfiguration.WebProxyInitialSetupRequired) + { + string text = "Would you like to enable the Novetus web proxy?\n\n" + + "A web proxy redirects web traffic to a different location and in some cases can act as a gateway to different sites. Novetus uses the web proxy for additional client features and asset redirection.\n\n" + + "When enabling the web proxy, Novetus will locally create a certificate upon startup that ensures the proxy's functionality. Novetus will not send any user data to anyone, as everything involving the web proxy is entirely local to this computer.\n" + + "If you have any issue connecting to other web sites, including Roblox, closing Novetus or typing 'proxy off' into Novetus' console will fix it in most instances.\n\n" + + "Upon pressing 'Yes', Windows will ask you for permission to install the certificate.\n\n" + + "You can change this option at any time by typing 'proxy disable' or 'proxy on' in the Novetus console. This message will appear only once.\n"; + + DialogResult result = MessageBox.Show(text, "Novetus - Web Proxy Opt-In", MessageBoxButtons.YesNo); + + switch (result) + { + case DialogResult.Yes: + GlobalVars.UserConfiguration.WebProxyEnabled = true; + Start(); + break; + case DialogResult.No: + default: + break; + } + + GlobalVars.UserConfiguration.WebProxyInitialSetupRequired = false; + FileManagement.Config(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ConfigName, true); + } + else + { + if (GlobalVars.UserConfiguration.WebProxyEnabled) + { Start(); - break; - case DialogResult.No: - default: - break; + } } - - GlobalVars.UserConfiguration.WebProxyInitialSetupRequired = false; - FileManagement.Config(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ConfigName, true); } - else + + public void Start() { - if (GlobalVars.UserConfiguration.WebProxyEnabled) + try { - Start(); + LoadExtensions(); + Server.CertificateManager.RootCertificateIssuerName = "Novetus"; + Server.CertificateManager.RootCertificateName = "Novetus Web Proxy"; + Server.BeforeRequest += new AsyncEventHandler(OnRequest); + UpdateEndPoint(true); + Util.ConsolePrint("Web Proxy started on port " + GlobalVars.WebProxyPort, 3); + foreach (IWebProxyExtension extension in ExtensionList.ToArray()) + { + extension.OnProxyStart(); + } } - } - } - - public void Start() - { - try - { - //load ext - Server.CertificateManager.RootCertificateIssuerName = "Novetus"; - Server.CertificateManager.RootCertificateName = "Novetus Web Proxy"; - Server.BeforeRequest += new AsyncEventHandler(OnRequest); - UpdateEndPoint(true); - Util.ConsolePrint("Web Proxy started on port " + GlobalVars.WebProxyPort, 3); - } - catch (Exception e) - { - Util.LogExceptions(e); - } - } - - public void UpdateEndPoint(bool shouldRunServer = false, bool decrypt = true) - { - if (Server.ProxyEndPoints.Count > 0) - { - Server.RemoveEndPoint(end); - } - - GlobalVars.WebProxyPort = GlobalVars.UserConfiguration.RobloxPort + 1; - end = new ExplicitProxyEndPoint(IPAddress.Any, GlobalVars.WebProxyPort, decrypt); - end.BeforeTunnelConnectRequest += new AsyncEventHandler(OnBeforeTunnelConnectRequest); - Server.AddEndPoint(end); - - if (!Server.ProxyRunning && shouldRunServer) - { - Server.Start(); - } - - if (Server.ProxyRunning) - { - foreach (ProxyEndPoint endPoint in Server.ProxyEndPoints) + catch (Exception e) { - Server.SetAsSystemHttpProxy(end); - Server.SetAsSystemHttpsProxy(end); + Util.LogExceptions(e); } } - Util.ConsolePrint("Web Proxy Endpoint updated with port " + GlobalVars.WebProxyPort, 3); - } - - private bool IsURIAllowed(HttpWebClient client) - { - string uri = client.Request.RequestUri.Host; - - if ((!uri.StartsWith("www.") && - !uri.StartsWith("web.") && - !uri.StartsWith("assetgame.") && - !uri.StartsWith("wiki.") && - !uri.EndsWith("api.roblox.com") && - !uri.StartsWith("roblox.com") || !uri.EndsWith("roblox.com")) && - !uri.EndsWith("robloxlabs.com")) + public void UpdateEndPoint(bool shouldRunServer = false, bool decrypt = true) { - return false; + if (Server.ProxyEndPoints.Count > 0) + { + Server.RemoveEndPoint(end); + } + + GlobalVars.WebProxyPort = GlobalVars.UserConfiguration.RobloxPort + 1; + end = new ExplicitProxyEndPoint(IPAddress.Any, GlobalVars.WebProxyPort, decrypt); + end.BeforeTunnelConnectRequest += new AsyncEventHandler(OnBeforeTunnelConnectRequest); + Server.AddEndPoint(end); + + if (!Server.ProxyRunning && shouldRunServer) + { + Server.Start(); + } + + if (Server.ProxyRunning) + { + foreach (ProxyEndPoint endPoint in Server.ProxyEndPoints) + { + Server.SetAsSystemHttpProxy(end); + Server.SetAsSystemHttpsProxy(end); + } + } + + Util.ConsolePrint("Web Proxy Endpoint updated with port " + GlobalVars.WebProxyPort, 3); } - //we check the header - HeaderCollection headers = client.Request.Headers; - List userAgents = headers.GetHeaders("User-Agent"); - - if (userAgents == null) - return false; - - if (string.IsNullOrWhiteSpace(userAgents.FirstOrDefault().Value)) - return false; - - string ua = userAgents.FirstOrDefault().Value.ToLowerInvariant(); - - //for some reason, this doesn't go through for the browser unless we look for mozilla/4.0. - //this shouldn't break modern mozilla browsers though. - return (ua.Contains("mozilla/4.0") || ua.Contains("roblox")); - } - - private Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) - { - if (!IsURIAllowed(e.HttpClient)) + private bool IsValidURL(HttpWebClient client) { - e.DecryptSsl = false; + string uri = client.Request.RequestUri.Host; + + if ((!uri.StartsWith("www.") && + !uri.StartsWith("web.") && + !uri.StartsWith("assetgame.") && + !uri.StartsWith("wiki.") && + !uri.EndsWith("api.roblox.com") && + !uri.StartsWith("roblox.com") || !uri.EndsWith("roblox.com")) && + !uri.EndsWith("robloxlabs.com")) + { + return false; + } + + //we check the header + HeaderCollection headers = client.Request.Headers; + List userAgents = headers.GetHeaders("User-Agent"); + + if (userAgents == null) + return false; + + if (string.IsNullOrWhiteSpace(userAgents.FirstOrDefault().Value)) + return false; + + string ua = userAgents.FirstOrDefault().Value.ToLowerInvariant(); + + //for some reason, this doesn't go through for the browser unless we look for mozilla/4.0. + //this shouldn't break modern mozilla browsers though. + return (ua.Contains("mozilla/4.0") || ua.Contains("roblox")); } - return Task.CompletedTask; - } + private Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) + { + if (!IsValidURL(e.HttpClient)) + { + e.DecryptSsl = false; + } + + Uri uri = e.HttpClient.Request.RequestUri; + + foreach (IWebProxyExtension extension in ExtensionList.ToArray()) + { + if (extension.IsValidURL(uri.AbsolutePath.ToLowerInvariant(), uri.Host)) + { + try + { + extension.OnBeforeTunnelConnectRequest(sender, e); + } + catch (Exception ex) + { + Util.LogExceptions(ex); + } + } + else + { + e.DecryptSsl = false; + } + } + + return Task.CompletedTask; + } #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously - private async Task OnRequest(object sender, SessionEventArgs e) + private async Task OnRequest(object sender, SessionEventArgs e) #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously - { - if (!IsURIAllowed(e.HttpClient)) { - return; + if (!IsValidURL(e.HttpClient)) + { + return; + } + + Uri uri = e.HttpClient.Request.RequestUri; + + foreach (IWebProxyExtension extension in ExtensionList.ToArray()) + { + if (extension.IsValidURL(uri.AbsolutePath.ToLowerInvariant(), uri.Host)) + { + try + { + await extension.OnRequest(sender, e); + return; + } + catch (Exception ex) + { + Util.LogExceptions(ex); + e.GenericResponse("", HttpStatusCode.InternalServerError); + return; + } + } + } + + e.GenericResponse("", HttpStatusCode.NotFound); } - e.GenericResponse("", HttpStatusCode.NotFound); + public void Stop() + { + Util.ConsolePrint("Web Proxy stopping on port " + GlobalVars.WebProxyPort, 3); + Server.BeforeRequest -= new AsyncEventHandler(OnRequest); + Server.Stop(); + + foreach (IWebProxyExtension extension in ExtensionList.ToArray()) + { + try + { + extension.OnProxyStopped(); + } + catch (Exception e) + { + Util.LogExceptions(e); + } + } + } } - - public void Stop() - { - Util.ConsolePrint("Web Proxy stopping on port " + GlobalVars.WebProxyPort, 3); - Server.BeforeRequest -= new AsyncEventHandler(OnRequest); - Server.Stop(); - } -} - -public interface IWebProxyExtention -{ - } #endif diff --git a/Novetus/NovetusCore/NovetusCore.projitems b/Novetus/NovetusCore/NovetusCore.projitems index 2657b69..2563963 100644 --- a/Novetus/NovetusCore/NovetusCore.projitems +++ b/Novetus/NovetusCore/NovetusCore.projitems @@ -9,6 +9,7 @@ NovetusCore + diff --git a/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs b/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs index 162621a..edd96bd 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs @@ -12,190 +12,192 @@ using System.Security.Cryptography; using System.Reflection; #endregion -#region Client Management -public class ClientManagement +namespace Novetus.Core { - public static void ReadClientValues(bool initial = false) + #region Client Management + public class ClientManagement { - ReadClientValues(GlobalVars.UserConfiguration.SelectedClient, initial); - } - - public static void ReadClientValues(string ClientName, bool initial = false) - { - string name = ClientName; - if (string.IsNullOrWhiteSpace(name)) + public static void ReadClientValues(bool initial = false) { - if (!string.IsNullOrWhiteSpace(GlobalVars.ProgramInformation.DefaultClient)) - { - name = GlobalVars.ProgramInformation.DefaultClient; - } - else - { - return; - } + ReadClientValues(GlobalVars.UserConfiguration.SelectedClient, initial); } - string clientpath = GlobalPaths.ClientDir + @"\\" + name + @"\\clientinfo.nov"; - - if (!File.Exists(clientpath)) + public static void ReadClientValues(string ClientName, bool initial = false) { - try + string name = ClientName; + if (string.IsNullOrWhiteSpace(name)) { - Util.ConsolePrint("ERROR - No clientinfo.nov detected with the client you chose. The client either cannot be loaded, or it is not available. Novetus will attempt to generate one.", 2); - GenerateDefaultClientInfo(Path.GetDirectoryName(clientpath)); - ReadClientValues(name, initial); + if (!string.IsNullOrWhiteSpace(GlobalVars.ProgramInformation.DefaultClient)) + { + name = GlobalVars.ProgramInformation.DefaultClient; + } + else + { + return; + } } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) + + string clientpath = GlobalPaths.ClientDir + @"\\" + name + @"\\clientinfo.nov"; + + if (!File.Exists(clientpath)) { - Util.LogExceptions(ex); + try + { + Util.ConsolePrint("ERROR - No clientinfo.nov detected with the client you chose. The client either cannot be loaded, or it is not available. Novetus will attempt to generate one.", 2); + GenerateDefaultClientInfo(Path.GetDirectoryName(clientpath)); + ReadClientValues(name, initial); + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); #else catch (Exception) { #endif - Util.ConsolePrint("ERROR - Failed to generate default clientinfo.nov. Info: " + ex.Message, 2); - Util.ConsolePrint("Loading default client '" + GlobalVars.ProgramInformation.DefaultClient + "'", 4); - name = GlobalVars.ProgramInformation.DefaultClient; - ReadClientValues(name, initial); - } - } - else - { - LoadClientValues(clientpath); - - if (initial) - { - Util.ConsolePrint("Client '" + name + "' successfully loaded.", 3); - } - } - - string terms = "_" + ClientName + "_default"; - string[] dirs = Directory.GetFiles(GlobalPaths.ConfigDirClients); - - foreach (string dir in dirs) - { - if (dir.Contains(terms) && dir.EndsWith(".xml")) - { - string fullpath = dir.Replace("_default", ""); - - if (!File.Exists(fullpath)) - { - Util.FixedFileCopy(dir, fullpath, false); + Util.ConsolePrint("ERROR - Failed to generate default clientinfo.nov. Info: " + ex.Message, 2); + Util.ConsolePrint("Loading default client '" + GlobalVars.ProgramInformation.DefaultClient + "'", 4); + name = GlobalVars.ProgramInformation.DefaultClient; + ReadClientValues(name, initial); } } + else + { + LoadClientValues(clientpath); + + if (initial) + { + Util.ConsolePrint("Client '" + name + "' successfully loaded.", 3); + } + } + + string terms = "_" + ClientName + "_default"; + string[] dirs = Directory.GetFiles(GlobalPaths.ConfigDirClients); + + foreach (string dir in dirs) + { + if (dir.Contains(terms) && dir.EndsWith(".xml")) + { + string fullpath = dir.Replace("_default", ""); + + if (!File.Exists(fullpath)) + { + Util.FixedFileCopy(dir, fullpath, false); + } + } + } + + ChangeGameSettings(ClientName); } - ChangeGameSettings(ClientName); - } + //Modified from https://stackoverflow.com/questions/4286487/is-there-any-lorem-ipsum-generator-in-c + public static string LoremIpsum(int minWords, int maxWords, + int minSentences, int maxSentences, + int numParagraphs) + { - //Modified from https://stackoverflow.com/questions/4286487/is-there-any-lorem-ipsum-generator-in-c - public static string LoremIpsum(int minWords, int maxWords, - int minSentences, int maxSentences, - int numParagraphs) - { - - var words = new[]{"lorem", "ipsum", "dolor", "sit", "amet", "consectetuer", + var words = new[]{"lorem", "ipsum", "dolor", "sit", "amet", "consectetuer", "adipiscing", "elit", "sed", "diam", "nonummy", "nibh", "euismod", "tincidunt", "ut", "laoreet", "dolore", "magna", "aliquam", "erat"}; - var rand = new Random(); - int numSentences = rand.Next(maxSentences - minSentences) - + minSentences + 1; - int numWords = rand.Next(maxWords - minWords) + minWords + 1; + var rand = new Random(); + int numSentences = rand.Next(maxSentences - minSentences) + + minSentences + 1; + int numWords = rand.Next(maxWords - minWords) + minWords + 1; - StringBuilder result = new StringBuilder(); + StringBuilder result = new StringBuilder(); - for (int p = 0; p < numParagraphs; p++) - { - result.Append("lorem ipsum "); - for (int s = 0; s < numSentences; s++) + for (int p = 0; p < numParagraphs; p++) { - for (int w = 0; w < numWords; w++) + result.Append("lorem ipsum "); + for (int s = 0; s < numSentences; s++) { - if (w > 0) { result.Append(" "); } - result.Append(words[rand.Next(words.Length)]); + for (int w = 0; w < numWords; w++) + { + if (w > 0) { result.Append(" "); } + result.Append(words[rand.Next(words.Length)]); + } + result.Append(". "); } - result.Append(". "); } + + return result.ToString(); } - return result.ToString(); - } - - //https://stackoverflow.com/questions/63879676/open-all-exe-files-in-a-directory-c-sharp - public static List GetAllExecutables(string path) - { - return Directory.Exists(path) - ? Directory.GetFiles(path, "*.exe").ToList() - : new List(); // or null - } - - public static void GenerateDefaultClientInfo(string path) - { - FileFormat.ClientInfo DefaultClientInfo = new FileFormat.ClientInfo(); - bool placeholder = false; - - string ClientName = ""; - List exeList = GetAllExecutables(path); - - if (File.Exists(path + "\\RobloxApp_client.exe")) + //https://stackoverflow.com/questions/63879676/open-all-exe-files-in-a-directory-c-sharp + public static List GetAllExecutables(string path) { - ClientName = "\\RobloxApp_client.exe"; - } - else if (File.Exists(path + "\\client\\RobloxApp_client.exe")) - { - ClientName = "\\client\\RobloxApp_client.exe"; - DefaultClientInfo.SeperateFolders = true; - } - else if (File.Exists(path + "\\RobloxApp.exe")) - { - ClientName = "\\RobloxApp.exe"; - DefaultClientInfo.LegacyMode = true; - } - else if (exeList.Count > 0) - { - string FirstEXE = exeList[0].Replace(path, "").Replace(@"\", ""); - ClientName = @"\\" + FirstEXE; - DefaultClientInfo.CustomClientEXEName = ClientName; - DefaultClientInfo.UsesCustomClientEXEName = true; - } - else - { - IOException clientNotFoundEX = new IOException("Could not find client exe file. Your client must have a .exe file to function."); - throw clientNotFoundEX; + return Directory.Exists(path) + ? Directory.GetFiles(path, "*.exe").ToList() + : new List(); // or null } - string ClientMD5 = File.Exists(path + ClientName) ? SecurityFuncs.GenerateMD5(path + ClientName) : ""; - - if (!string.IsNullOrWhiteSpace(ClientMD5)) + public static void GenerateDefaultClientInfo(string path) { - DefaultClientInfo.ClientMD5 = ClientMD5.ToUpper(CultureInfo.InvariantCulture); - } - else - { - IOException clientNotFoundEX = new IOException("Could not find client exe for MD5 generation. It must be named either RobloxApp.exe or RobloxApp_client.exe in order to function."); - throw clientNotFoundEX; - } + FileFormat.ClientInfo DefaultClientInfo = new FileFormat.ClientInfo(); + bool placeholder = false; - string ClientScriptMD5 = File.Exists(path + "\\content\\scripts\\" + GlobalPaths.ScriptName + ".lua") ? SecurityFuncs.GenerateMD5(path + "\\content\\scripts\\" + GlobalPaths.ScriptName + ".lua") : ""; + string ClientName = ""; + List exeList = GetAllExecutables(path); - if (!string.IsNullOrWhiteSpace(ClientScriptMD5)) - { - DefaultClientInfo.ScriptMD5 = ClientScriptMD5.ToUpper(CultureInfo.InvariantCulture); - } - /*else - { - IOException clientNotFoundEX = new IOException("Could not find script file for MD5 generation. You must have a CSMPFunctions.lua script in your client's content/scripts folder."); - throw clientNotFoundEX; - }*/ + if (File.Exists(path + "\\RobloxApp_client.exe")) + { + ClientName = "\\RobloxApp_client.exe"; + } + else if (File.Exists(path + "\\client\\RobloxApp_client.exe")) + { + ClientName = "\\client\\RobloxApp_client.exe"; + DefaultClientInfo.SeperateFolders = true; + } + else if (File.Exists(path + "\\RobloxApp.exe")) + { + ClientName = "\\RobloxApp.exe"; + DefaultClientInfo.LegacyMode = true; + } + else if (exeList.Count > 0) + { + string FirstEXE = exeList[0].Replace(path, "").Replace(@"\", ""); + ClientName = @"\\" + FirstEXE; + DefaultClientInfo.CustomClientEXEName = ClientName; + DefaultClientInfo.UsesCustomClientEXEName = true; + } + else + { + IOException clientNotFoundEX = new IOException("Could not find client exe file. Your client must have a .exe file to function."); + throw clientNotFoundEX; + } - string desc = "This client information file for '" + GlobalVars.UserConfiguration.SelectedClient + - "' was pre-generated by Novetus for your convienence. You will need to load this clientinfo.nov file into the Client SDK for additional options. " - + LoremIpsum(1, 128, 1, 6, 1); + string ClientMD5 = File.Exists(path + ClientName) ? SecurityFuncs.GenerateMD5(path + ClientName) : ""; - DefaultClientInfo.Description = desc; + if (!string.IsNullOrWhiteSpace(ClientMD5)) + { + DefaultClientInfo.ClientMD5 = ClientMD5.ToUpper(CultureInfo.InvariantCulture); + } + else + { + IOException clientNotFoundEX = new IOException("Could not find client exe for MD5 generation. It must be named either RobloxApp.exe or RobloxApp_client.exe in order to function."); + throw clientNotFoundEX; + } - string[] lines = { + string ClientScriptMD5 = File.Exists(path + "\\content\\scripts\\" + GlobalPaths.ScriptName + ".lua") ? SecurityFuncs.GenerateMD5(path + "\\content\\scripts\\" + GlobalPaths.ScriptName + ".lua") : ""; + + if (!string.IsNullOrWhiteSpace(ClientScriptMD5)) + { + DefaultClientInfo.ScriptMD5 = ClientScriptMD5.ToUpper(CultureInfo.InvariantCulture); + } + /*else + { + IOException clientNotFoundEX = new IOException("Could not find script file for MD5 generation. You must have a CSMPFunctions.lua script in your client's content/scripts folder."); + throw clientNotFoundEX; + }*/ + + string desc = "This client information file for '" + GlobalVars.UserConfiguration.SelectedClient + + "' was pre-generated by Novetus for your convienence. You will need to load this clientinfo.nov file into the Client SDK for additional options. " + + LoremIpsum(1, 128, 1, 6, 1); + + DefaultClientInfo.Description = desc; + + string[] lines = { SecurityFuncs.Base64Encode(DefaultClientInfo.UsesPlayerName.ToString()), SecurityFuncs.Base64Encode(DefaultClientInfo.UsesID.ToString()), SecurityFuncs.Base64Encode(DefaultClientInfo.Warning.ToString()), @@ -213,362 +215,443 @@ public class ClientManagement SecurityFuncs.Base64Encode(DefaultClientInfo.CommandLineArgs.ToString()) }; - File.WriteAllText(path + "\\clientinfo.nov", SecurityFuncs.Base64Encode(string.Join("|", lines))); - } - - //NOT FOR SDK. - public static FileFormat.ClientInfo GetClientInfoValues(string ClientName) - { - string name = ClientName; - - try - { - FileFormat.ClientInfo info = new FileFormat.ClientInfo(); - string clientpath = GlobalPaths.ClientDir + @"\\" + name + @"\\clientinfo.nov"; - LoadClientValues(info, clientpath); - return info; + File.WriteAllText(path + "\\clientinfo.nov", SecurityFuncs.Base64Encode(string.Join("|", lines))); } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) + + //NOT FOR SDK. + public static FileFormat.ClientInfo GetClientInfoValues(string ClientName) { - Util.LogExceptions(ex); + string name = ClientName; + + try + { + FileFormat.ClientInfo info = new FileFormat.ClientInfo(); + string clientpath = GlobalPaths.ClientDir + @"\\" + name + @"\\clientinfo.nov"; + LoadClientValues(info, clientpath); + return info; + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); #else catch (Exception) { #endif - return null; - } - } - - public static void LoadClientValues(string clientpath) - { - LoadClientValues(GlobalVars.SelectedClientInfo, clientpath); - } - - public static void LoadClientValues(FileFormat.ClientInfo info, string clientpath) - { - string file, usesplayername, usesid, warning, - legacymode, clientmd5, scriptmd5, - desc, fix2007, alreadyhassecurity, - clientloadoptions, commandlineargs, folders, - usescustomname, customname; - - using (StreamReader reader = new StreamReader(clientpath)) - { - file = reader.ReadLine(); + return null; + } } - string ConvertedLine = SecurityFuncs.Base64Decode(file); - string[] result = ConvertedLine.Split('|'); - usesplayername = SecurityFuncs.Base64Decode(result[0]); - usesid = SecurityFuncs.Base64Decode(result[1]); - warning = SecurityFuncs.Base64Decode(result[2]); - legacymode = SecurityFuncs.Base64Decode(result[3]); - clientmd5 = SecurityFuncs.Base64Decode(result[4]); - scriptmd5 = SecurityFuncs.Base64Decode(result[5]); - desc = SecurityFuncs.Base64Decode(result[6]); - fix2007 = SecurityFuncs.Base64Decode(result[8]); - alreadyhassecurity = SecurityFuncs.Base64Decode(result[9]); - clientloadoptions = SecurityFuncs.Base64Decode(result[10]); - folders = "False"; - usescustomname = "False"; - customname = ""; - try + public static void LoadClientValues(string clientpath) { - commandlineargs = SecurityFuncs.Base64Decode(result[11]); + LoadClientValues(GlobalVars.SelectedClientInfo, clientpath); + } - bool parsedValue; - if (bool.TryParse(commandlineargs, out parsedValue)) + public static void LoadClientValues(FileFormat.ClientInfo info, string clientpath) + { + string file, usesplayername, usesid, warning, + legacymode, clientmd5, scriptmd5, + desc, fix2007, alreadyhassecurity, + clientloadoptions, commandlineargs, folders, + usescustomname, customname; + + using (StreamReader reader = new StreamReader(clientpath)) { - folders = SecurityFuncs.Base64Decode(result[11]); - commandlineargs = SecurityFuncs.Base64Decode(result[12]); - bool parsedValue2; - if (bool.TryParse(commandlineargs, out parsedValue2)) + file = reader.ReadLine(); + } + + string ConvertedLine = SecurityFuncs.Base64Decode(file); + string[] result = ConvertedLine.Split('|'); + usesplayername = SecurityFuncs.Base64Decode(result[0]); + usesid = SecurityFuncs.Base64Decode(result[1]); + warning = SecurityFuncs.Base64Decode(result[2]); + legacymode = SecurityFuncs.Base64Decode(result[3]); + clientmd5 = SecurityFuncs.Base64Decode(result[4]); + scriptmd5 = SecurityFuncs.Base64Decode(result[5]); + desc = SecurityFuncs.Base64Decode(result[6]); + fix2007 = SecurityFuncs.Base64Decode(result[8]); + alreadyhassecurity = SecurityFuncs.Base64Decode(result[9]); + clientloadoptions = SecurityFuncs.Base64Decode(result[10]); + folders = "False"; + usescustomname = "False"; + customname = ""; + try + { + commandlineargs = SecurityFuncs.Base64Decode(result[11]); + + bool parsedValue; + if (bool.TryParse(commandlineargs, out parsedValue)) { - usescustomname = SecurityFuncs.Base64Decode(result[12]); - customname = SecurityFuncs.Base64Decode(result[13]); - commandlineargs = SecurityFuncs.Base64Decode(result[14]); - } - } - } - catch (Exception) - { - //fake this option until we properly apply it. - clientloadoptions = "2"; - commandlineargs = SecurityFuncs.Base64Decode(result[10]); - } - - info.UsesPlayerName = Convert.ToBoolean(usesplayername); - info.UsesID = Convert.ToBoolean(usesid); - info.Warning = warning; - info.LegacyMode = Convert.ToBoolean(legacymode); - info.ClientMD5 = clientmd5; - info.ScriptMD5 = scriptmd5; - info.Description = desc; - info.Fix2007 = Convert.ToBoolean(fix2007); - info.AlreadyHasSecurity = Convert.ToBoolean(alreadyhassecurity); - if (clientloadoptions.Equals("True") || clientloadoptions.Equals("False")) - { - info.ClientLoadOptions = Settings.GetClientLoadOptionsForBool(Convert.ToBoolean(clientloadoptions)); - } - else - { - info.ClientLoadOptions = (Settings.ClientLoadOptions)Convert.ToInt32(clientloadoptions); - } - - info.SeperateFolders = Convert.ToBoolean(folders); - info.UsesCustomClientEXEName = Convert.ToBoolean(usescustomname); - info.CustomClientEXEName = customname; - info.CommandLineArgs = commandlineargs; - } - - public static GlobalVars.LauncherState GetStateForType(ScriptType type) - { - switch (type) - { - case ScriptType.Client: - return GlobalVars.LauncherState.InMPGame; - case ScriptType.Solo: - return GlobalVars.LauncherState.InSoloGame; - case ScriptType.Studio: - return GlobalVars.LauncherState.InStudio; - case ScriptType.EasterEgg: - return GlobalVars.LauncherState.InEasterEggGame; - default: - return GlobalVars.LauncherState.InLauncher; - } - } - - public static void UpdateRichPresence(GlobalVars.LauncherState state, bool initial = false) - { - string mapname = ""; - if (GlobalVars.GameOpened != ScriptType.Client) - { - mapname = GlobalVars.UserConfiguration.Map; - } - - UpdateRichPresence(state, GlobalVars.UserConfiguration.SelectedClient, mapname, initial); - } - - public static void UpdateRichPresence(GlobalVars.LauncherState state, string mapname, bool initial = false) - { - UpdateRichPresence(state, GlobalVars.UserConfiguration.SelectedClient, mapname, initial); - } - - public static void UpdateRichPresence(GlobalVars.LauncherState state, string clientname, string mapname, bool initial = false) - { - if (GlobalVars.UserConfiguration.DiscordPresence) - { - if (initial) - { - GlobalVars.presence.largeImageKey = GlobalVars.imagekey_large; - GlobalVars.presence.startTimestamp = SecurityFuncs.UnixTimeNow(); - } - - string ValidMapname = (string.IsNullOrWhiteSpace(mapname) ? "Place1" : mapname); - - switch (state) - { - case GlobalVars.LauncherState.InLauncher: - GlobalVars.presence.smallImageKey = GlobalVars.image_inlauncher; - GlobalVars.presence.state = "In Launcher"; - GlobalVars.presence.details = "Selected " + clientname; - GlobalVars.presence.largeImageText = GlobalVars.UserConfiguration.PlayerName + " | Novetus " + GlobalVars.ProgramInformation.Version; - GlobalVars.presence.smallImageText = "In Launcher"; - break; - case GlobalVars.LauncherState.InMPGame: - GlobalVars.presence.smallImageKey = GlobalVars.image_ingame; - GlobalVars.presence.details = ValidMapname; - GlobalVars.presence.state = "In " + clientname + " Multiplayer Game"; - GlobalVars.presence.largeImageText = GlobalVars.UserConfiguration.PlayerName + " | Novetus " + GlobalVars.ProgramInformation.Version; - GlobalVars.presence.smallImageText = "In " + clientname + " Multiplayer Game"; - break; - case GlobalVars.LauncherState.InSoloGame: - GlobalVars.presence.smallImageKey = GlobalVars.image_ingame; - GlobalVars.presence.details = ValidMapname; - GlobalVars.presence.state = "In " + clientname + " Solo Game"; - GlobalVars.presence.largeImageText = GlobalVars.UserConfiguration.PlayerName + " | Novetus " + GlobalVars.ProgramInformation.Version; - GlobalVars.presence.smallImageText = "In " + clientname + " Solo Game"; - break; - case GlobalVars.LauncherState.InStudio: - GlobalVars.presence.smallImageKey = GlobalVars.image_instudio; - GlobalVars.presence.details = ValidMapname; - GlobalVars.presence.state = "In " + clientname + " Studio"; - GlobalVars.presence.largeImageText = GlobalVars.UserConfiguration.PlayerName + " | Novetus " + GlobalVars.ProgramInformation.Version; - GlobalVars.presence.smallImageText = "In " + clientname + " Studio"; - break; - case GlobalVars.LauncherState.InCustomization: - GlobalVars.presence.smallImageKey = GlobalVars.image_incustomization; - GlobalVars.presence.details = "Customizing " + GlobalVars.UserConfiguration.PlayerName; - GlobalVars.presence.state = "In Character Customization"; - GlobalVars.presence.largeImageText = GlobalVars.UserConfiguration.PlayerName + " | Novetus " + GlobalVars.ProgramInformation.Version; - GlobalVars.presence.smallImageText = "In Character Customization"; - break; - case GlobalVars.LauncherState.InEasterEggGame: - GlobalVars.presence.smallImageKey = GlobalVars.image_ingame; - GlobalVars.presence.details = ValidMapname; - GlobalVars.presence.state = "Reading a message."; - GlobalVars.presence.largeImageText = GlobalVars.UserConfiguration.PlayerName + " | Novetus " + GlobalVars.ProgramInformation.Version; - GlobalVars.presence.smallImageText = "Reading a message."; - break; - case GlobalVars.LauncherState.LoadingURI: - GlobalVars.presence.smallImageKey = GlobalVars.image_ingame; - GlobalVars.presence.details = ValidMapname; - GlobalVars.presence.state = "Joining a " + clientname + " Multiplayer Game"; - GlobalVars.presence.largeImageText = GlobalVars.UserConfiguration.PlayerName + " | Novetus " + GlobalVars.ProgramInformation.Version; - GlobalVars.presence.smallImageText = "Joining a " + clientname + " Multiplayer Game"; - break; - default: - break; - } - - DiscordRPC.UpdatePresence(ref GlobalVars.presence); - } - } - - public static void ChangeGameSettings(string ClientName) - { - try - { - FileFormat.ClientInfo info = GetClientInfoValues(ClientName); - - string filterPath = GlobalPaths.ConfigDir + @"\\" + GlobalPaths.FileDeleteFilterName; - string[] fileListToDelete = File.ReadAllLines(filterPath); - - foreach (string file in fileListToDelete) - { - string fullFilePath = Settings.GetPathForClientLoadOptions(info.ClientLoadOptions) + @"\" + file; - Util.FixedFileDelete(fullFilePath); - } - - if (GlobalVars.UserConfiguration.QualityLevel != Settings.Level.Custom) - { - int GraphicsMode = 0; - - if (info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomaticQL21 || - info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomatic) - { - GraphicsMode = 1; - } - else - { - if (info.ClientLoadOptions != Settings.ClientLoadOptions.Client_2007_NoGraphicsOptions || - info.ClientLoadOptions != Settings.ClientLoadOptions.Client_2008AndUp_NoGraphicsOptions) + folders = SecurityFuncs.Base64Decode(result[11]); + commandlineargs = SecurityFuncs.Base64Decode(result[12]); + bool parsedValue2; + if (bool.TryParse(commandlineargs, out parsedValue2)) { - - switch (GlobalVars.UserConfiguration.GraphicsMode) - { - case Settings.Mode.OpenGLStable: - switch (info.ClientLoadOptions) - { - case Settings.ClientLoadOptions.Client_2007: - case Settings.ClientLoadOptions.Client_2008AndUp_LegacyOpenGL: - case Settings.ClientLoadOptions.Client_2008AndUp_HasCharacterOnlyShadowsLegacyOpenGL: - GraphicsMode = 2; - break; - case Settings.ClientLoadOptions.Client_2008AndUp: - case Settings.ClientLoadOptions.Client_2008AndUp_QualityLevel21: - GraphicsMode = 4; - break; - default: - break; - } - break; - case Settings.Mode.OpenGLExperimental: - GraphicsMode = 4; - break; - case Settings.Mode.DirectX: - GraphicsMode = 3; - break; - default: - GraphicsMode = 1; - break; - } + usescustomname = SecurityFuncs.Base64Decode(result[12]); + customname = SecurityFuncs.Base64Decode(result[13]); + commandlineargs = SecurityFuncs.Base64Decode(result[14]); } } + } + catch (Exception) + { + //fake this option until we properly apply it. + clientloadoptions = "2"; + commandlineargs = SecurityFuncs.Base64Decode(result[10]); + } - //default values are ultra settings - int MeshDetail = 100; - int ShadingQuality = 100; - int GFXQualityLevel = 19; - if (info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomaticQL21 || - info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_QualityLevel21) + info.UsesPlayerName = Convert.ToBoolean(usesplayername); + info.UsesID = Convert.ToBoolean(usesid); + info.Warning = warning; + info.LegacyMode = Convert.ToBoolean(legacymode); + info.ClientMD5 = clientmd5; + info.ScriptMD5 = scriptmd5; + info.Description = desc; + info.Fix2007 = Convert.ToBoolean(fix2007); + info.AlreadyHasSecurity = Convert.ToBoolean(alreadyhassecurity); + if (clientloadoptions.Equals("True") || clientloadoptions.Equals("False")) + { + info.ClientLoadOptions = Settings.GetClientLoadOptionsForBool(Convert.ToBoolean(clientloadoptions)); + } + else + { + info.ClientLoadOptions = (Settings.ClientLoadOptions)Convert.ToInt32(clientloadoptions); + } + + info.SeperateFolders = Convert.ToBoolean(folders); + info.UsesCustomClientEXEName = Convert.ToBoolean(usescustomname); + info.CustomClientEXEName = customname; + info.CommandLineArgs = commandlineargs; + } + + public static GlobalVars.LauncherState GetStateForType(ScriptType type) + { + switch (type) + { + case ScriptType.Client: + return GlobalVars.LauncherState.InMPGame; + case ScriptType.Solo: + return GlobalVars.LauncherState.InSoloGame; + case ScriptType.Studio: + return GlobalVars.LauncherState.InStudio; + case ScriptType.EasterEgg: + return GlobalVars.LauncherState.InEasterEggGame; + default: + return GlobalVars.LauncherState.InLauncher; + } + } + + public static void UpdateRichPresence(GlobalVars.LauncherState state, bool initial = false) + { + string mapname = ""; + if (GlobalVars.GameOpened != ScriptType.Client) + { + mapname = GlobalVars.UserConfiguration.Map; + } + + UpdateRichPresence(state, GlobalVars.UserConfiguration.SelectedClient, mapname, initial); + } + + public static void UpdateRichPresence(GlobalVars.LauncherState state, string mapname, bool initial = false) + { + UpdateRichPresence(state, GlobalVars.UserConfiguration.SelectedClient, mapname, initial); + } + + public static void UpdateRichPresence(GlobalVars.LauncherState state, string clientname, string mapname, bool initial = false) + { + if (GlobalVars.UserConfiguration.DiscordPresence) + { + if (initial) { - GFXQualityLevel = 21; + GlobalVars.presence.largeImageKey = GlobalVars.imagekey_large; + GlobalVars.presence.startTimestamp = SecurityFuncs.UnixTimeNow(); } - int MaterialQuality = 3; - int AASamples = 8; - int Bevels = 1; - int Shadows_2008 = 1; - int AA = 1; - bool Shadows_2007 = true; - switch (GlobalVars.UserConfiguration.QualityLevel) + string ValidMapname = (string.IsNullOrWhiteSpace(mapname) ? "Place1" : mapname); + + switch (state) { - case Settings.Level.Automatic: - //set everything to automatic. Some ultra settings will still be enabled. - AA = 0; - Bevels = 0; - Shadows_2008 = 0; - GFXQualityLevel = 0; - MaterialQuality = 0; - Shadows_2007 = false; + case GlobalVars.LauncherState.InLauncher: + GlobalVars.presence.smallImageKey = GlobalVars.image_inlauncher; + GlobalVars.presence.state = "In Launcher"; + GlobalVars.presence.details = "Selected " + clientname; + GlobalVars.presence.largeImageText = GlobalVars.UserConfiguration.PlayerName + " | Novetus " + GlobalVars.ProgramInformation.Version; + GlobalVars.presence.smallImageText = "In Launcher"; break; - case Settings.Level.VeryLow: - AA = 2; - MeshDetail = 50; - ShadingQuality = 50; - GFXQualityLevel = 1; - MaterialQuality = 1; - AASamples = 1; - Bevels = 2; - Shadows_2008 = 2; - Shadows_2007 = false; + case GlobalVars.LauncherState.InMPGame: + GlobalVars.presence.smallImageKey = GlobalVars.image_ingame; + GlobalVars.presence.details = ValidMapname; + GlobalVars.presence.state = "In " + clientname + " Multiplayer Game"; + GlobalVars.presence.largeImageText = GlobalVars.UserConfiguration.PlayerName + " | Novetus " + GlobalVars.ProgramInformation.Version; + GlobalVars.presence.smallImageText = "In " + clientname + " Multiplayer Game"; break; - case Settings.Level.Low: - AA = 2; - MeshDetail = 50; - ShadingQuality = 50; - GFXQualityLevel = 5; - MaterialQuality = 1; - AASamples = 1; - Bevels = 2; - Shadows_2008 = 2; - Shadows_2007 = false; + case GlobalVars.LauncherState.InSoloGame: + GlobalVars.presence.smallImageKey = GlobalVars.image_ingame; + GlobalVars.presence.details = ValidMapname; + GlobalVars.presence.state = "In " + clientname + " Solo Game"; + GlobalVars.presence.largeImageText = GlobalVars.UserConfiguration.PlayerName + " | Novetus " + GlobalVars.ProgramInformation.Version; + GlobalVars.presence.smallImageText = "In " + clientname + " Solo Game"; break; - case Settings.Level.Medium: - MeshDetail = 75; - ShadingQuality = 75; - GFXQualityLevel = 10; - MaterialQuality = 2; - AASamples = 4; - Bevels = 2; - if (info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomatic || - info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomaticQL21 || - info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_QualityLevel21 || - info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_HasCharacterOnlyShadowsLegacyOpenGL) - { - Shadows_2008 = 3; - } - Shadows_2007 = false; + case GlobalVars.LauncherState.InStudio: + GlobalVars.presence.smallImageKey = GlobalVars.image_instudio; + GlobalVars.presence.details = ValidMapname; + GlobalVars.presence.state = "In " + clientname + " Studio"; + GlobalVars.presence.largeImageText = GlobalVars.UserConfiguration.PlayerName + " | Novetus " + GlobalVars.ProgramInformation.Version; + GlobalVars.presence.smallImageText = "In " + clientname + " Studio"; break; - case Settings.Level.High: - MeshDetail = 75; - ShadingQuality = 75; - GFXQualityLevel = 15; - AASamples = 4; + case GlobalVars.LauncherState.InCustomization: + GlobalVars.presence.smallImageKey = GlobalVars.image_incustomization; + GlobalVars.presence.details = "Customizing " + GlobalVars.UserConfiguration.PlayerName; + GlobalVars.presence.state = "In Character Customization"; + GlobalVars.presence.largeImageText = GlobalVars.UserConfiguration.PlayerName + " | Novetus " + GlobalVars.ProgramInformation.Version; + GlobalVars.presence.smallImageText = "In Character Customization"; + break; + case GlobalVars.LauncherState.InEasterEggGame: + GlobalVars.presence.smallImageKey = GlobalVars.image_ingame; + GlobalVars.presence.details = ValidMapname; + GlobalVars.presence.state = "Reading a message."; + GlobalVars.presence.largeImageText = GlobalVars.UserConfiguration.PlayerName + " | Novetus " + GlobalVars.ProgramInformation.Version; + GlobalVars.presence.smallImageText = "Reading a message."; + break; + case GlobalVars.LauncherState.LoadingURI: + GlobalVars.presence.smallImageKey = GlobalVars.image_ingame; + GlobalVars.presence.details = ValidMapname; + GlobalVars.presence.state = "Joining a " + clientname + " Multiplayer Game"; + GlobalVars.presence.largeImageText = GlobalVars.UserConfiguration.PlayerName + " | Novetus " + GlobalVars.ProgramInformation.Version; + GlobalVars.presence.smallImageText = "Joining a " + clientname + " Multiplayer Game"; break; - case Settings.Level.Ultra: default: break; } - ApplyClientSettings(info, ClientName, GraphicsMode, MeshDetail, ShadingQuality, MaterialQuality, AA, AASamples, Bevels, - Shadows_2008, Shadows_2007, "", GFXQualityLevel, "800x600", "1024x768", 0); + DiscordRPC.UpdatePresence(ref GlobalVars.presence); } - else + } + + public static void ChangeGameSettings(string ClientName) + { + try + { + FileFormat.ClientInfo info = GetClientInfoValues(ClientName); + + string filterPath = GlobalPaths.ConfigDir + @"\\" + GlobalPaths.FileDeleteFilterName; + string[] fileListToDelete = File.ReadAllLines(filterPath); + + foreach (string file in fileListToDelete) + { + string fullFilePath = Settings.GetPathForClientLoadOptions(info.ClientLoadOptions) + @"\" + file; + Util.FixedFileDelete(fullFilePath); + } + + if (GlobalVars.UserConfiguration.QualityLevel != Settings.Level.Custom) + { + int GraphicsMode = 0; + + if (info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomaticQL21 || + info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomatic) + { + GraphicsMode = 1; + } + else + { + if (info.ClientLoadOptions != Settings.ClientLoadOptions.Client_2007_NoGraphicsOptions || + info.ClientLoadOptions != Settings.ClientLoadOptions.Client_2008AndUp_NoGraphicsOptions) + { + + switch (GlobalVars.UserConfiguration.GraphicsMode) + { + case Settings.Mode.OpenGLStable: + switch (info.ClientLoadOptions) + { + case Settings.ClientLoadOptions.Client_2007: + case Settings.ClientLoadOptions.Client_2008AndUp_LegacyOpenGL: + case Settings.ClientLoadOptions.Client_2008AndUp_HasCharacterOnlyShadowsLegacyOpenGL: + GraphicsMode = 2; + break; + case Settings.ClientLoadOptions.Client_2008AndUp: + case Settings.ClientLoadOptions.Client_2008AndUp_QualityLevel21: + GraphicsMode = 4; + break; + default: + break; + } + break; + case Settings.Mode.OpenGLExperimental: + GraphicsMode = 4; + break; + case Settings.Mode.DirectX: + GraphicsMode = 3; + break; + default: + GraphicsMode = 1; + break; + } + } + } + + //default values are ultra settings + int MeshDetail = 100; + int ShadingQuality = 100; + int GFXQualityLevel = 19; + if (info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomaticQL21 || + info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_QualityLevel21) + { + GFXQualityLevel = 21; + } + int MaterialQuality = 3; + int AASamples = 8; + int Bevels = 1; + int Shadows_2008 = 1; + int AA = 1; + bool Shadows_2007 = true; + + switch (GlobalVars.UserConfiguration.QualityLevel) + { + case Settings.Level.Automatic: + //set everything to automatic. Some ultra settings will still be enabled. + AA = 0; + Bevels = 0; + Shadows_2008 = 0; + GFXQualityLevel = 0; + MaterialQuality = 0; + Shadows_2007 = false; + break; + case Settings.Level.VeryLow: + AA = 2; + MeshDetail = 50; + ShadingQuality = 50; + GFXQualityLevel = 1; + MaterialQuality = 1; + AASamples = 1; + Bevels = 2; + Shadows_2008 = 2; + Shadows_2007 = false; + break; + case Settings.Level.Low: + AA = 2; + MeshDetail = 50; + ShadingQuality = 50; + GFXQualityLevel = 5; + MaterialQuality = 1; + AASamples = 1; + Bevels = 2; + Shadows_2008 = 2; + Shadows_2007 = false; + break; + case Settings.Level.Medium: + MeshDetail = 75; + ShadingQuality = 75; + GFXQualityLevel = 10; + MaterialQuality = 2; + AASamples = 4; + Bevels = 2; + if (info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomatic || + info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomaticQL21 || + info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_QualityLevel21 || + info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_HasCharacterOnlyShadowsLegacyOpenGL) + { + Shadows_2008 = 3; + } + Shadows_2007 = false; + break; + case Settings.Level.High: + MeshDetail = 75; + ShadingQuality = 75; + GFXQualityLevel = 15; + AASamples = 4; + break; + case Settings.Level.Ultra: + default: + break; + } + + ApplyClientSettings(info, ClientName, GraphicsMode, MeshDetail, ShadingQuality, MaterialQuality, AA, AASamples, Bevels, + Shadows_2008, Shadows_2007, "", GFXQualityLevel, "800x600", "1024x768", 0); + } + else + { + //save graphics mode. + int GraphicsMode = 0; + + if (info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomaticQL21 || + info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomatic) + { + GraphicsMode = 1; + } + else + { + if (info.ClientLoadOptions != Settings.ClientLoadOptions.Client_2007_NoGraphicsOptions || + info.ClientLoadOptions != Settings.ClientLoadOptions.Client_2008AndUp_NoGraphicsOptions) + { + + switch (GlobalVars.UserConfiguration.GraphicsMode) + { + case Settings.Mode.OpenGLStable: + switch (info.ClientLoadOptions) + { + case Settings.ClientLoadOptions.Client_2007: + case Settings.ClientLoadOptions.Client_2008AndUp_LegacyOpenGL: + case Settings.ClientLoadOptions.Client_2008AndUp_HasCharacterOnlyShadowsLegacyOpenGL: + GraphicsMode = 2; + break; + case Settings.ClientLoadOptions.Client_2008AndUp: + case Settings.ClientLoadOptions.Client_2008AndUp_QualityLevel21: + GraphicsMode = 4; + break; + default: + break; + } + break; + case Settings.Mode.OpenGLExperimental: + GraphicsMode = 4; + break; + case Settings.Mode.DirectX: + GraphicsMode = 3; + break; + default: + GraphicsMode = 1; + break; + } + } + } + + ApplyClientSettings(info, ClientName, GraphicsMode, 0, 0, 0, 0, 0, 0, 0, false, "", 0, "800x600", "1024x768", 0, true); + + //just copy the file. + string terms = "_" + ClientName; + string[] dirs = Directory.GetFiles(GlobalPaths.ConfigDirClients); + + foreach (string dir in dirs) + { + if (dir.Contains(terms) && !dir.Contains("_default")) + { + Util.FixedFileCopy(dir, Settings.GetPathForClientLoadOptions(info.ClientLoadOptions) + @"\" + Path.GetFileName(dir).Replace(terms, "") + .Replace(dir.Substring(dir.LastIndexOf('-') + 1), "") + .Replace("-", ".xml"), true); + } + } + } + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); +#else + catch (Exception) + { +#endif + return; + } + } + + //oh god.... + //we're using this one for custom graphics quality. Better than the latter. + public static void ApplyClientSettings_custom(FileFormat.ClientInfo info, string ClientName, int MeshDetail, int ShadingQuality, int MaterialQuality, + int AA, int AASamples, int Bevels, int Shadows_2008, bool Shadows_2007, string Style_2007, int GFXQualityLevel, string WindowResolution, string FullscreenResolution, + int ModernResolution) + { + try { - //save graphics mode. int GraphicsMode = 0; if (info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomaticQL21 || @@ -581,7 +664,6 @@ public class ClientManagement if (info.ClientLoadOptions != Settings.ClientLoadOptions.Client_2007_NoGraphicsOptions || info.ClientLoadOptions != Settings.ClientLoadOptions.Client_2008AndUp_NoGraphicsOptions) { - switch (GlobalVars.UserConfiguration.GraphicsMode) { case Settings.Mode.OpenGLStable: @@ -613,9 +695,31 @@ public class ClientManagement } } - ApplyClientSettings(info, ClientName, GraphicsMode, 0, 0, 0, 0, 0, 0, 0, false, "", 0, "800x600", "1024x768", 0, true); + ApplyClientSettings(info, ClientName, GraphicsMode, MeshDetail, ShadingQuality, MaterialQuality, + AA, AASamples, Bevels, Shadows_2008, Shadows_2007, Style_2007, GFXQualityLevel, WindowResolution, FullscreenResolution, ModernResolution); + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); +#else + catch (Exception) + { +#endif + return; + } + } + + //it's worse. + public static void ApplyClientSettings(FileFormat.ClientInfo info, string ClientName, int GraphicsMode, int MeshDetail, int ShadingQuality, int MaterialQuality, + int AA, int AASamples, int Bevels, int Shadows_2008, bool Shadows_2007, string Style_2007, int GFXQualityLevel, string WindowResolution, string FullscreenResolution, + int ModernResolution, bool onlyGraphicsMode = false) + { + try + { + string winRes = WindowResolution; + string fullRes = FullscreenResolution; - //just copy the file. string terms = "_" + ClientName; string[] dirs = Directory.GetFiles(GlobalPaths.ConfigDirClients); @@ -623,362 +727,260 @@ public class ClientManagement { if (dir.Contains(terms) && !dir.Contains("_default")) { - Util.FixedFileCopy(dir, Settings.GetPathForClientLoadOptions(info.ClientLoadOptions) + @"\" + Path.GetFileName(dir).Replace(terms, "") - .Replace(dir.Substring(dir.LastIndexOf('-') + 1), "") - .Replace("-", ".xml"), true); - } - } - } - } + string oldfile = ""; + string fixedfile = ""; + XDocument doc = null; + + try + { + oldfile = File.ReadAllText(dir); + fixedfile = RobloxXML.RemoveInvalidXmlChars(RobloxXML.ReplaceHexadecimalSymbols(oldfile)); + doc = XDocument.Parse(fixedfile); + } #if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); + catch (Exception ex) + { + Util.LogExceptions(ex); #else - catch (Exception) - { + catch (Exception) + { #endif - return; - } - } + return; + } - //oh god.... - //we're using this one for custom graphics quality. Better than the latter. - public static void ApplyClientSettings_custom(FileFormat.ClientInfo info, string ClientName, int MeshDetail, int ShadingQuality, int MaterialQuality, - int AA, int AASamples, int Bevels, int Shadows_2008, bool Shadows_2007, string Style_2007, int GFXQualityLevel, string WindowResolution, string FullscreenResolution, - int ModernResolution) - { - try - { - int GraphicsMode = 0; - - if (info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomaticQL21 || - info.ClientLoadOptions == Settings.ClientLoadOptions.Client_2008AndUp_ForceAutomatic) - { - GraphicsMode = 1; - } - else - { - if (info.ClientLoadOptions != Settings.ClientLoadOptions.Client_2007_NoGraphicsOptions || - info.ClientLoadOptions != Settings.ClientLoadOptions.Client_2008AndUp_NoGraphicsOptions) - { - switch (GlobalVars.UserConfiguration.GraphicsMode) - { - case Settings.Mode.OpenGLStable: - switch (info.ClientLoadOptions) + try + { + if (GraphicsMode != 0) { - case Settings.ClientLoadOptions.Client_2007: - case Settings.ClientLoadOptions.Client_2008AndUp_LegacyOpenGL: - case Settings.ClientLoadOptions.Client_2008AndUp_HasCharacterOnlyShadowsLegacyOpenGL: - GraphicsMode = 2; - break; - case Settings.ClientLoadOptions.Client_2008AndUp: - case Settings.ClientLoadOptions.Client_2008AndUp_QualityLevel21: - GraphicsMode = 4; - break; - default: - break; + RobloxXML.EditRenderSettings(doc, "graphicsMode", GraphicsMode.ToString(), XMLTypes.Token); } - break; - case Settings.Mode.OpenGLExperimental: - GraphicsMode = 4; - break; - case Settings.Mode.DirectX: - GraphicsMode = 3; - break; - default: - GraphicsMode = 1; - break; - } - } - } - ApplyClientSettings(info, ClientName, GraphicsMode, MeshDetail, ShadingQuality, MaterialQuality, - AA, AASamples, Bevels, Shadows_2008, Shadows_2007, Style_2007, GFXQualityLevel, WindowResolution, FullscreenResolution, ModernResolution); - } + if (!onlyGraphicsMode) + { + RobloxXML.EditRenderSettings(doc, "maxMeshDetail", MeshDetail.ToString(), XMLTypes.Float); + RobloxXML.EditRenderSettings(doc, "maxShadingQuality", ShadingQuality.ToString(), XMLTypes.Float); + RobloxXML.EditRenderSettings(doc, "minMeshDetail", MeshDetail.ToString(), XMLTypes.Float); + RobloxXML.EditRenderSettings(doc, "minShadingQuality", ShadingQuality.ToString(), XMLTypes.Float); + RobloxXML.EditRenderSettings(doc, "AluminumQuality", MaterialQuality.ToString(), XMLTypes.Token); + RobloxXML.EditRenderSettings(doc, "CompoundMaterialQuality", MaterialQuality.ToString(), XMLTypes.Token); + RobloxXML.EditRenderSettings(doc, "CorrodedMetalQuality", MaterialQuality.ToString(), XMLTypes.Token); + RobloxXML.EditRenderSettings(doc, "DiamondPlateQuality", MaterialQuality.ToString(), XMLTypes.Token); + RobloxXML.EditRenderSettings(doc, "GrassQuality", MaterialQuality.ToString(), XMLTypes.Token); + RobloxXML.EditRenderSettings(doc, "IceQuality", MaterialQuality.ToString(), XMLTypes.Token); + RobloxXML.EditRenderSettings(doc, "PlasticQuality", MaterialQuality.ToString(), XMLTypes.Token); + RobloxXML.EditRenderSettings(doc, "SlateQuality", MaterialQuality.ToString(), XMLTypes.Token); + // fix truss detail. We're keeping it at 0. + RobloxXML.EditRenderSettings(doc, "TrussDetail", MaterialQuality.ToString(), XMLTypes.Token); + RobloxXML.EditRenderSettings(doc, "WoodQuality", MaterialQuality.ToString(), XMLTypes.Token); + RobloxXML.EditRenderSettings(doc, "Antialiasing", AA.ToString(), XMLTypes.Token); + RobloxXML.EditRenderSettings(doc, "AASamples", AASamples.ToString(), XMLTypes.Token); + RobloxXML.EditRenderSettings(doc, "Bevels", Bevels.ToString(), XMLTypes.Token); + RobloxXML.EditRenderSettings(doc, "Shadow", Shadows_2008.ToString(), XMLTypes.Token); + RobloxXML.EditRenderSettings(doc, "Shadows", Shadows_2007.ToString().ToLower(), XMLTypes.Bool); + RobloxXML.EditRenderSettings(doc, "shadows", Shadows_2007.ToString().ToLower(), XMLTypes.Bool); + RobloxXML.EditRenderSettings(doc, "_skinFile", !string.IsNullOrWhiteSpace(Style_2007) ? @"Styles\" + Style_2007 : "", XMLTypes.String); + RobloxXML.EditRenderSettings(doc, "QualityLevel", GFXQualityLevel.ToString(), XMLTypes.Token); + RobloxXML.EditRenderSettings(doc, "FullscreenSizePreference", fullRes.ToString(), XMLTypes.Vector2Int16); + RobloxXML.EditRenderSettings(doc, "FullscreenSize", fullRes.ToString(), XMLTypes.Vector2Int16); + RobloxXML.EditRenderSettings(doc, "WindowSizePreference", winRes.ToString(), XMLTypes.Vector2Int16); + RobloxXML.EditRenderSettings(doc, "WindowSize", winRes.ToString(), XMLTypes.Vector2Int16); + RobloxXML.EditRenderSettings(doc, "Resolution", ModernResolution.ToString(), XMLTypes.Token); + } + } #if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif - return; - } - } - - //it's worse. - public static void ApplyClientSettings(FileFormat.ClientInfo info, string ClientName, int GraphicsMode, int MeshDetail, int ShadingQuality, int MaterialQuality, - int AA, int AASamples, int Bevels, int Shadows_2008, bool Shadows_2007, string Style_2007, int GFXQualityLevel, string WindowResolution, string FullscreenResolution, - int ModernResolution, bool onlyGraphicsMode = false) - { - try - { - string winRes = WindowResolution; - string fullRes = FullscreenResolution; - - string terms = "_" + ClientName; - string[] dirs = Directory.GetFiles(GlobalPaths.ConfigDirClients); - - foreach (string dir in dirs) - { - if (dir.Contains(terms) && !dir.Contains("_default")) - { - string oldfile = ""; - string fixedfile = ""; - XDocument doc = null; - - try - { - oldfile = File.ReadAllText(dir); - fixedfile = RobloxXML.RemoveInvalidXmlChars(RobloxXML.ReplaceHexadecimalSymbols(oldfile)); - doc = XDocument.Parse(fixedfile); - } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); + catch (Exception ex) + { + Util.LogExceptions(ex); #else catch (Exception) { #endif - return; - } - - try - { - if (GraphicsMode != 0) - { - RobloxXML.EditRenderSettings(doc, "graphicsMode", GraphicsMode.ToString(), XMLTypes.Token); + return; } - - if (!onlyGraphicsMode) + finally { - RobloxXML.EditRenderSettings(doc, "maxMeshDetail", MeshDetail.ToString(), XMLTypes.Float); - RobloxXML.EditRenderSettings(doc, "maxShadingQuality", ShadingQuality.ToString(), XMLTypes.Float); - RobloxXML.EditRenderSettings(doc, "minMeshDetail", MeshDetail.ToString(), XMLTypes.Float); - RobloxXML.EditRenderSettings(doc, "minShadingQuality", ShadingQuality.ToString(), XMLTypes.Float); - RobloxXML.EditRenderSettings(doc, "AluminumQuality", MaterialQuality.ToString(), XMLTypes.Token); - RobloxXML.EditRenderSettings(doc, "CompoundMaterialQuality", MaterialQuality.ToString(), XMLTypes.Token); - RobloxXML.EditRenderSettings(doc, "CorrodedMetalQuality", MaterialQuality.ToString(), XMLTypes.Token); - RobloxXML.EditRenderSettings(doc, "DiamondPlateQuality", MaterialQuality.ToString(), XMLTypes.Token); - RobloxXML.EditRenderSettings(doc, "GrassQuality", MaterialQuality.ToString(), XMLTypes.Token); - RobloxXML.EditRenderSettings(doc, "IceQuality", MaterialQuality.ToString(), XMLTypes.Token); - RobloxXML.EditRenderSettings(doc, "PlasticQuality", MaterialQuality.ToString(), XMLTypes.Token); - RobloxXML.EditRenderSettings(doc, "SlateQuality", MaterialQuality.ToString(), XMLTypes.Token); - // fix truss detail. We're keeping it at 0. - RobloxXML.EditRenderSettings(doc, "TrussDetail", MaterialQuality.ToString(), XMLTypes.Token); - RobloxXML.EditRenderSettings(doc, "WoodQuality", MaterialQuality.ToString(), XMLTypes.Token); - RobloxXML.EditRenderSettings(doc, "Antialiasing", AA.ToString(), XMLTypes.Token); - RobloxXML.EditRenderSettings(doc, "AASamples", AASamples.ToString(), XMLTypes.Token); - RobloxXML.EditRenderSettings(doc, "Bevels", Bevels.ToString(), XMLTypes.Token); - RobloxXML.EditRenderSettings(doc, "Shadow", Shadows_2008.ToString(), XMLTypes.Token); - RobloxXML.EditRenderSettings(doc, "Shadows", Shadows_2007.ToString().ToLower(), XMLTypes.Bool); - RobloxXML.EditRenderSettings(doc, "shadows", Shadows_2007.ToString().ToLower(), XMLTypes.Bool); - RobloxXML.EditRenderSettings(doc, "_skinFile", !string.IsNullOrWhiteSpace(Style_2007) ? @"Styles\" + Style_2007 : "", XMLTypes.String); - RobloxXML.EditRenderSettings(doc, "QualityLevel", GFXQualityLevel.ToString(), XMLTypes.Token); - RobloxXML.EditRenderSettings(doc, "FullscreenSizePreference", fullRes.ToString(), XMLTypes.Vector2Int16); - RobloxXML.EditRenderSettings(doc, "FullscreenSize", fullRes.ToString(), XMLTypes.Vector2Int16); - RobloxXML.EditRenderSettings(doc, "WindowSizePreference", winRes.ToString(), XMLTypes.Vector2Int16); - RobloxXML.EditRenderSettings(doc, "WindowSize", winRes.ToString(), XMLTypes.Vector2Int16); - RobloxXML.EditRenderSettings(doc, "Resolution", ModernResolution.ToString(), XMLTypes.Token); + doc.Save(dir); + Util.FixedFileCopy(dir, Settings.GetPathForClientLoadOptions(info.ClientLoadOptions) + @"\" + Path.GetFileName(dir).Replace(terms, "") + .Replace(dir.Substring(dir.LastIndexOf('-') + 1), "") + .Replace("-", ".xml"), true); } } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif - return; - } - finally - { - doc.Save(dir); - Util.FixedFileCopy(dir, Settings.GetPathForClientLoadOptions(info.ClientLoadOptions) + @"\" + Path.GetFileName(dir).Replace(terms, "") - .Replace(dir.Substring(dir.LastIndexOf('-') + 1), "") - .Replace("-", ".xml"), true); - } } } - } #if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); + catch (Exception ex) + { + Util.LogExceptions(ex); #else catch (Exception) { #endif - return; - } - } - - public static string GetGenLuaFileName(string ClientName, ScriptType type) - { - string luafile = ""; - - bool rbxasset = GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%userbxassetforgeneration%"); - - if (!rbxasset) - { - if (GlobalVars.SelectedClientInfo.SeperateFolders) - { - luafile = GlobalPaths.ClientDir + @"\\" + ClientName + @"\\" + GetClientSeperateFolderName(type) + @"\\content\\scripts\\" + GlobalPaths.ScriptGenName + ".lua"; - } - else - { - luafile = GlobalPaths.ClientDir + @"\\" + ClientName + @"\\content\\scripts\\" + GlobalPaths.ScriptGenName + ".lua"; + return; } } - else + + public static string GetGenLuaFileName(string ClientName, ScriptType type) { - luafile = @"rbxasset://scripts\\" + GlobalPaths.ScriptGenName + ".lua"; - } + string luafile = ""; - return luafile; - } + bool rbxasset = GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%userbxassetforgeneration%"); - public static string GetLuaFileName(ScriptType type) - { - return GetLuaFileName(GlobalVars.UserConfiguration.SelectedClient, type); - } - - public static string GetLuaFileName(string ClientName, ScriptType type) - { - string luafile = ""; - - if (!GlobalVars.SelectedClientInfo.Fix2007) - { - bool HasGenerateScript = false; - - foreach (string line in GlobalVars.SelectedClientInfo.CommandLineArgs.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)) + if (!rbxasset) { - if (line.Contains("%generatescript%")) + if (GlobalVars.SelectedClientInfo.SeperateFolders) { - HasGenerateScript = true; + luafile = GlobalPaths.ClientDir + @"\\" + ClientName + @"\\" + GetClientSeperateFolderName(type) + @"\\content\\scripts\\" + GlobalPaths.ScriptGenName + ".lua"; + } + else + { + luafile = GlobalPaths.ClientDir + @"\\" + ClientName + @"\\content\\scripts\\" + GlobalPaths.ScriptGenName + ".lua"; } } - - if (HasGenerateScript) + else { - luafile = ScriptFuncs.Generator.GetGeneratedScriptName(ClientName, type); + luafile = @"rbxasset://scripts\\" + GlobalPaths.ScriptGenName + ".lua"; + } + + return luafile; + } + + public static string GetLuaFileName(ScriptType type) + { + return GetLuaFileName(GlobalVars.UserConfiguration.SelectedClient, type); + } + + public static string GetLuaFileName(string ClientName, ScriptType type) + { + string luafile = ""; + + if (!GlobalVars.SelectedClientInfo.Fix2007) + { + bool HasGenerateScript = false; + + foreach (string line in GlobalVars.SelectedClientInfo.CommandLineArgs.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)) + { + if (line.Contains("%generatescript%")) + { + HasGenerateScript = true; + } + } + + if (HasGenerateScript) + { + luafile = ScriptFuncs.Generator.GetGeneratedScriptName(ClientName, type); + } + else + { + luafile = "rbxasset://scripts\\\\" + GlobalPaths.ScriptName + ".lua"; + } } else { - luafile = "rbxasset://scripts\\\\" + GlobalPaths.ScriptName + ".lua"; + luafile = GetGenLuaFileName(ClientName, type); } - } - else - { - luafile = GetGenLuaFileName(ClientName, type); + + return luafile; } - return luafile; - } - - public static string GetClientSeperateFolderName(ScriptType type) - { - string rbxfolder = ""; - switch (type) - { - case ScriptType.Client: - case ScriptType.Solo: - case ScriptType.EasterEgg: - rbxfolder = "client"; - break; - case ScriptType.Server: - rbxfolder = "server"; - break; - case ScriptType.Studio: - rbxfolder = "studio"; - break; - case ScriptType.None: - default: - rbxfolder = ""; - break; - } - - return rbxfolder; - } - - public static string GetClientEXEDir(ScriptType type) - { - return GetClientEXEDir(GlobalVars.UserConfiguration.SelectedClient, type); - } - - public static string GetClientEXEDir(string ClientName, ScriptType type) - { - string rbxexe = ""; - string BasePath = GlobalPaths.ClientDir + @"\\" + ClientName; - if (GlobalVars.SelectedClientInfo.LegacyMode) - { - rbxexe = BasePath + @"\\RobloxApp.exe"; - } - else if (GlobalVars.SelectedClientInfo.UsesCustomClientEXEName) - { - rbxexe = BasePath + @"\\" + GlobalVars.SelectedClientInfo.CustomClientEXEName; - } - else if (GlobalVars.SelectedClientInfo.SeperateFolders) + public static string GetClientSeperateFolderName(ScriptType type) { + string rbxfolder = ""; switch (type) { case ScriptType.Client: case ScriptType.Solo: case ScriptType.EasterEgg: - rbxexe = BasePath + @"\\" + GetClientSeperateFolderName(type) + @"\\RobloxApp_client.exe"; + rbxfolder = "client"; break; case ScriptType.Server: - rbxexe = BasePath + @"\\" + GetClientSeperateFolderName(type) + @"\\RobloxApp_server.exe"; + rbxfolder = "server"; break; case ScriptType.Studio: - rbxexe = BasePath + @"\\" + GetClientSeperateFolderName(type) + @"\\RobloxApp_studio.exe"; + rbxfolder = "studio"; break; case ScriptType.None: default: - rbxexe = BasePath + @"\\RobloxApp.exe"; - break; - } - } - else - { - switch (type) - { - case ScriptType.Client: - rbxexe = BasePath + @"\\RobloxApp_client.exe"; - break; - case ScriptType.Server: - rbxexe = BasePath + @"\\RobloxApp_server.exe"; - break; - case ScriptType.Studio: - rbxexe = BasePath + @"\\RobloxApp_studio.exe"; - break; - case ScriptType.Solo: - case ScriptType.EasterEgg: - rbxexe = BasePath + @"\\RobloxApp_solo.exe"; - break; - case ScriptType.None: - default: - rbxexe = BasePath + @"\\RobloxApp.exe"; + rbxfolder = ""; break; } + + return rbxfolder; } - return rbxexe; - } + public static string GetClientEXEDir(ScriptType type) + { + return GetClientEXEDir(GlobalVars.UserConfiguration.SelectedClient, type); + } + + public static string GetClientEXEDir(string ClientName, ScriptType type) + { + string rbxexe = ""; + string BasePath = GlobalPaths.ClientDir + @"\\" + ClientName; + if (GlobalVars.SelectedClientInfo.LegacyMode) + { + rbxexe = BasePath + @"\\RobloxApp.exe"; + } + else if (GlobalVars.SelectedClientInfo.UsesCustomClientEXEName) + { + rbxexe = BasePath + @"\\" + GlobalVars.SelectedClientInfo.CustomClientEXEName; + } + else if (GlobalVars.SelectedClientInfo.SeperateFolders) + { + switch (type) + { + case ScriptType.Client: + case ScriptType.Solo: + case ScriptType.EasterEgg: + rbxexe = BasePath + @"\\" + GetClientSeperateFolderName(type) + @"\\RobloxApp_client.exe"; + break; + case ScriptType.Server: + rbxexe = BasePath + @"\\" + GetClientSeperateFolderName(type) + @"\\RobloxApp_server.exe"; + break; + case ScriptType.Studio: + rbxexe = BasePath + @"\\" + GetClientSeperateFolderName(type) + @"\\RobloxApp_studio.exe"; + break; + case ScriptType.None: + default: + rbxexe = BasePath + @"\\RobloxApp.exe"; + break; + } + } + else + { + switch (type) + { + case ScriptType.Client: + rbxexe = BasePath + @"\\RobloxApp_client.exe"; + break; + case ScriptType.Server: + rbxexe = BasePath + @"\\RobloxApp_server.exe"; + break; + case ScriptType.Studio: + rbxexe = BasePath + @"\\RobloxApp_studio.exe"; + break; + case ScriptType.Solo: + case ScriptType.EasterEgg: + rbxexe = BasePath + @"\\RobloxApp_solo.exe"; + break; + case ScriptType.None: + default: + rbxexe = BasePath + @"\\RobloxApp.exe"; + break; + } + } + + return rbxexe; + } #if URI - public static void UpdateStatus(Label label, string status) - { - Util.LogPrint(status); - if (label != null) + public static void UpdateStatus(Label label, string status) { - label.Text = status; + Util.LogPrint(status); + if (label != null) + { + label.Text = status; + } } - } #endif #if LAUNCHER @@ -1012,36 +1014,36 @@ public class ClientManagement #endif #if URI - public static void LaunchRBXClient(ScriptType type, bool no3d, bool nomap, EventHandler e, Label label) + public static void LaunchRBXClient(ScriptType type, bool no3d, bool nomap, EventHandler e, Label label) #else public static void LaunchRBXClient(ScriptType type, bool no3d, bool nomap, EventHandler e) #endif - { + { #if URI - LaunchRBXClient(GlobalVars.UserConfiguration.SelectedClient, type, no3d, nomap, e, label); + LaunchRBXClient(GlobalVars.UserConfiguration.SelectedClient, type, no3d, nomap, e, label); #else LaunchRBXClient(GlobalVars.UserConfiguration.SelectedClient, type, no3d, nomap, e); #endif - } + } #if URI - public static void ValidateFiles(string line, string validstart, string validend, Label label) + public static void ValidateFiles(string line, string validstart, string validend, Label label) #else public static void ValidateFiles(string line, string validstart, string validend) #endif - { - string extractedFile = ScriptFuncs.ClientScript.GetArgsFromTag(line, validstart, validend); - if (!string.IsNullOrWhiteSpace(extractedFile)) { - string[] parsedFileParams = extractedFile.Split('|'); - string filePath = parsedFileParams[0]; - string fileMD5 = parsedFileParams[1]; - string fullFilePath = GlobalPaths.ClientDir + @"\\" + GlobalVars.UserConfiguration.SelectedClient + @"\\" + filePath; - - if (!SecurityFuncs.CheckMD5(fileMD5, fullFilePath)) + string extractedFile = ScriptFuncs.ClientScript.GetArgsFromTag(line, validstart, validend); + if (!string.IsNullOrWhiteSpace(extractedFile)) { + string[] parsedFileParams = extractedFile.Split('|'); + string filePath = parsedFileParams[0]; + string fileMD5 = parsedFileParams[1]; + string fullFilePath = GlobalPaths.ClientDir + @"\\" + GlobalVars.UserConfiguration.SelectedClient + @"\\" + filePath; + + if (!SecurityFuncs.CheckMD5(fileMD5, fullFilePath)) + { #if URI - UpdateStatus(label, "The client has been detected as modified."); + UpdateStatus(label, "The client has been detected as modified."); #elif LAUNCHER Util.ConsolePrint("ERROR - Failed to launch Novetus. (The client has been detected as modified.)", 2); #endif @@ -1054,41 +1056,41 @@ public class ClientManagement #endif #if URI - throw new IOException("The client has been detected as modified."); + throw new IOException("The client has been detected as modified."); #else return; #endif - } - else - { - GlobalVars.ValidatedExtraFiles += 1; + } + else + { + GlobalVars.ValidatedExtraFiles += 1; + } } } - } #if URI - public static void LaunchRBXClient(string ClientName, ScriptType type, bool no3d, bool nomap, EventHandler e, Label label) + public static void LaunchRBXClient(string ClientName, ScriptType type, bool no3d, bool nomap, EventHandler e, Label label) #else public static void LaunchRBXClient(string ClientName, ScriptType type, bool no3d, bool nomap, EventHandler e) #endif - { - #if LAUNCHER - DecompressMap(type, nomap); - #endif - - switch (type) { - case ScriptType.Client: - FileManagement.ReloadLoadoutValue(true); - if (!GlobalVars.LocalPlayMode && GlobalVars.GameOpened != ScriptType.Server) - { - goto default; - } - break; - case ScriptType.Server: - if (GlobalVars.GameOpened == ScriptType.Server) - { - Util.ConsolePrint("ERROR - Failed to launch Novetus. (A server is already running.)", 2); +#if LAUNCHER + DecompressMap(type, nomap); +#endif + + switch (type) + { + case ScriptType.Client: + FileManagement.ReloadLoadoutValue(true); + if (!GlobalVars.LocalPlayMode && GlobalVars.GameOpened != ScriptType.Server) + { + goto default; + } + break; + case ScriptType.Server: + if (GlobalVars.GameOpened == ScriptType.Server) + { + Util.ConsolePrint("ERROR - Failed to launch Novetus. (A server is already running.)", 2); #if LAUNCHER if (!GlobalVars.isConsoleOnly) @@ -1096,10 +1098,10 @@ public class ClientManagement MessageBox.Show("Failed to launch Novetus. (Error: A server is already running.)", "Novetus - Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } #endif - return; - } - else if (GlobalVars.UserConfiguration.FirstServerLaunch) - { + return; + } + else if (GlobalVars.UserConfiguration.FirstServerLaunch) + { #if LAUNCHER string hostingTips = "For your first time hosting a server, make sure your server's port forwarded (set up in your router), going through a tunnel server, or running from UPnP.\n" + "If your port is forwarded or you are going through a tunnel server, make sure your port is set up as UDP, not TCP.\n" + @@ -1114,20 +1116,20 @@ public class ClientManagement Util.ConsolePrint("Tips: " + hostingTips, 4); } #endif - GlobalVars.UserConfiguration.FirstServerLaunch = false; - } - else - { + GlobalVars.UserConfiguration.FirstServerLaunch = false; + } + else + { + goto default; + } + break; + case ScriptType.Solo: + FileManagement.ReloadLoadoutValue(true); goto default; - } - break; - case ScriptType.Solo: - FileManagement.ReloadLoadoutValue(true); - goto default; - default: - if (GlobalVars.GameOpened != ScriptType.None) - { - Util.ConsolePrint("ERROR - Failed to launch Novetus. (A game is already running.)", 2); + default: + if (GlobalVars.GameOpened != ScriptType.None) + { + Util.ConsolePrint("ERROR - Failed to launch Novetus. (A game is already running.)", 2); #if LAUNCHER if (!GlobalVars.isConsoleOnly) @@ -1135,141 +1137,141 @@ public class ClientManagement MessageBox.Show("Failed to launch Novetus. (Error: A game is already running.)", "Novetus - Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } #endif - return; - } - break; - } + return; + } + break; + } - ReadClientValues(ClientName); - string luafile = GetLuaFileName(ClientName, type); - string rbxexe = GetClientEXEDir(ClientName, type); - string mapfile = type.Equals(ScriptType.EasterEgg) ? - GlobalPaths.DataDir + "\\Appreciation.rbxl" : - (nomap ? (type.Equals(ScriptType.Studio) ? GlobalPaths.ConfigDir + "\\Place1.rbxl" : "") : GlobalVars.UserConfiguration.MapPath); - string mapname = type.Equals(ScriptType.EasterEgg) ? "" : (nomap ? "" : GlobalVars.UserConfiguration.Map); - FileFormat.ClientInfo info = GetClientInfoValues(ClientName); - string quote = "\""; - string args = ""; - GlobalVars.ValidatedExtraFiles = 0; + ReadClientValues(ClientName); + string luafile = GetLuaFileName(ClientName, type); + string rbxexe = GetClientEXEDir(ClientName, type); + string mapfile = type.Equals(ScriptType.EasterEgg) ? + GlobalPaths.DataDir + "\\Appreciation.rbxl" : + (nomap ? (type.Equals(ScriptType.Studio) ? GlobalPaths.ConfigDir + "\\Place1.rbxl" : "") : GlobalVars.UserConfiguration.MapPath); + string mapname = type.Equals(ScriptType.EasterEgg) ? "" : (nomap ? "" : GlobalVars.UserConfiguration.Map); + FileFormat.ClientInfo info = GetClientInfoValues(ClientName); + string quote = "\""; + string args = ""; + GlobalVars.ValidatedExtraFiles = 0; - bool v1 = false; + bool v1 = false; - if (info.CommandLineArgs.Contains("<") && - info.CommandLineArgs.Contains("")) - { - v1 = true; - } - - if (!GlobalVars.AdminMode && !info.AlreadyHasSecurity) - { - string validstart = ""; - string validend = ""; - string validv2 = "validate="; - - foreach (string line in info.CommandLineArgs.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)) + if (info.CommandLineArgs.Contains("<") && + info.CommandLineArgs.Contains("")) { - if (v1 && line.Contains(validstart) && line.Contains(validend)) + v1 = true; + } + + if (!GlobalVars.AdminMode && !info.AlreadyHasSecurity) + { + string validstart = ""; + string validend = ""; + string validv2 = "validate="; + + foreach (string line in info.CommandLineArgs.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)) { - try + if (v1 && line.Contains(validstart) && line.Contains(validend)) { + try + { #if URI - ValidateFiles(line, validstart, validend, label); + ValidateFiles(line, validstart, validend, label); #else ValidateFiles(line, validstart, validend); #endif - } + } #if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); + catch (Exception ex) + { + Util.LogExceptions(ex); #else catch (Exception) { #endif - continue; + continue; + } } - } - else if (line.Contains(validv2)) - { - try + else if (line.Contains(validv2)) { + try + { #if URI - ValidateFiles(line, validv2, "", label); + ValidateFiles(line, validv2, "", label); #else ValidateFiles(line, validv2, ""); #endif - } + } #if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); + catch (Exception ex) + { + Util.LogExceptions(ex); #else catch (Exception) { #endif - continue; + continue; + } } } } - } - if (info.CommandLineArgs.Contains("%args%")) - { - if (!info.Fix2007) + if (info.CommandLineArgs.Contains("%args%")) { - args = quote - + mapfile - + "\" -script \" dofile('" + luafile + "'); " - + ScriptFuncs.Generator.GetScriptFuncForType(ClientName, type) - + quote - + (no3d ? " -no3d" : ""); + if (!info.Fix2007) + { + args = quote + + mapfile + + "\" -script \" dofile('" + luafile + "'); " + + ScriptFuncs.Generator.GetScriptFuncForType(ClientName, type) + + quote + + (no3d ? " -no3d" : ""); + } + else + { + ScriptFuncs.Generator.GenerateScriptForClient(ClientName, type); + args = "-script " + + quote + + luafile + + quote + + (no3d ? " -no3d" : "") + + " " + + quote + + mapfile + + quote; + } } else { - ScriptFuncs.Generator.GenerateScriptForClient(ClientName, type); - args = "-script " - + quote - + luafile - + quote - + (no3d ? " -no3d" : "") - + " " - + quote - + mapfile - + quote; + args = ScriptFuncs.ClientScript.CompileScript(ClientName, info.CommandLineArgs, + ScriptFuncs.ClientScript.GetTagFromType(type, false, no3d, v1), + ScriptFuncs.ClientScript.GetTagFromType(type, true, no3d, v1), + mapfile, + luafile, + rbxexe); } - } - else - { - args = ScriptFuncs.ClientScript.CompileScript(ClientName, info.CommandLineArgs, - ScriptFuncs.ClientScript.GetTagFromType(type, false, no3d, v1), - ScriptFuncs.ClientScript.GetTagFromType(type, true, no3d, v1), - mapfile, - luafile, - rbxexe); - } - if (args == "") - return; + if (args == "") + return; - try - { - Util.ConsolePrint("Client Loaded.", 4); - - if (type.Equals(ScriptType.Client)) + try { - if (!GlobalVars.AdminMode) + Util.ConsolePrint("Client Loaded.", 4); + + if (type.Equals(ScriptType.Client)) { - if (info.AlreadyHasSecurity != true) + if (!GlobalVars.AdminMode) { - if (SecurityFuncs.checkClientMD5(ClientName) && SecurityFuncs.checkScriptMD5(ClientName)) - { - OpenClient(type, rbxexe, args, ClientName, mapname, e); - } - else + if (info.AlreadyHasSecurity != true) { + if (SecurityFuncs.checkClientMD5(ClientName) && SecurityFuncs.checkScriptMD5(ClientName)) + { + OpenClient(type, rbxexe, args, ClientName, mapname, e); + } + else + { #if URI - UpdateStatus(label, "The client has been detected as modified."); + UpdateStatus(label, "The client has been detected as modified."); #elif LAUNCHER Util.ConsolePrint("ERROR - Failed to launch Novetus. (The client has been detected as modified.)", 2); #endif @@ -1282,10 +1284,15 @@ public class ClientManagement #endif #if URI - throw new IOException("The client has been detected as modified."); + throw new IOException("The client has been detected as modified."); #else return; #endif + } + } + else + { + OpenClient(type, rbxexe, args, ClientName, mapname, e); } } else @@ -1297,258 +1304,253 @@ public class ClientManagement { OpenClient(type, rbxexe, args, ClientName, mapname, e); } - } - else - { - OpenClient(type, rbxexe, args, ClientName, mapname, e); - } - switch (type) - { - case ScriptType.Client: - if (!GlobalVars.LocalPlayMode && GlobalVars.GameOpened != ScriptType.Server) - { + switch (type) + { + case ScriptType.Client: + if (!GlobalVars.LocalPlayMode && GlobalVars.GameOpened != ScriptType.Server) + { + goto default; + } + break; + case ScriptType.Studio: + break; + case ScriptType.Server: + NovetusFuncs.PingMasterServer(true, "Server will now display on the defined master server, if available."); goto default; - } - break; - case ScriptType.Studio: - break; - case ScriptType.Server: - NovetusFuncs.PingMasterServer(true, "Server will now display on the defined master server, if available."); - goto default; - default: - GlobalVars.GameOpened = type; - break; - } + default: + GlobalVars.GameOpened = type; + break; + } - GlobalVars.ValidatedExtraFiles = 0; - } + GlobalVars.ValidatedExtraFiles = 0; + } #if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) + catch (Exception ex) #else catch (Exception) #endif - { + { #if URI - UpdateStatus(label, "Error: " + ex.Message); + UpdateStatus(label, "Error: " + ex.Message); #elif LAUNCHER Util.ConsolePrint("ERROR - Failed to launch Novetus. (Error: " + ex.Message + ")", 2); #endif #if URI || LAUNCHER - if (!GlobalVars.isConsoleOnly) - { - MessageBox.Show("Failed to launch Novetus. (Error: " + ex.Message + ")", "Novetus - Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } + if (!GlobalVars.isConsoleOnly) + { + MessageBox.Show("Failed to launch Novetus. (Error: " + ex.Message + ")", "Novetus - Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } #endif #if URI || LAUNCHER || BASICLAUNCHER - Util.LogExceptions(ex); + Util.LogExceptions(ex); #endif #if URI - //toss the exception back to the URI - throw new Exception(ex.Message); + //toss the exception back to the URI + throw new Exception(ex.Message); #endif - } - } - - public static void OpenClient(ScriptType type, string rbxexe, string args, string clientname, string mapname, EventHandler e, bool customization = false) - { - Process client = new Process(); - client.StartInfo.FileName = rbxexe; - client.StartInfo.WorkingDirectory = Path.GetDirectoryName(rbxexe); - client.StartInfo.Arguments = args; - if (e != null) - { - client.EnableRaisingEvents = true; - client.Exited += e; - } - client.Start(); - client.PriorityClass = GlobalVars.UserConfiguration.Priority; - - if (!customization) - { - SecurityFuncs.RenameWindow(client, type, clientname, mapname); - if (e != null) - { - UpdateRichPresence(GetStateForType(type), clientname, mapname); } } - //TODO: make a command that uses this. + public static void OpenClient(ScriptType type, string rbxexe, string args, string clientname, string mapname, EventHandler e, bool customization = false) + { + Process client = new Process(); + client.StartInfo.FileName = rbxexe; + client.StartInfo.WorkingDirectory = Path.GetDirectoryName(rbxexe); + client.StartInfo.Arguments = args; + if (e != null) + { + client.EnableRaisingEvents = true; + client.Exited += e; + } + client.Start(); + client.PriorityClass = GlobalVars.UserConfiguration.Priority; + + if (!customization) + { + SecurityFuncs.RenameWindow(client, type, clientname, mapname); + if (e != null) + { + UpdateRichPresence(GetStateForType(type), clientname, mapname); + } + } + + //TODO: make a command that uses this. #if CMD_LEGACY NovetusFuncs.CreateTXT(); #endif - } - - public static bool IsClientValid(string client) - { - string clientdir = GlobalPaths.ClientDir; - DirectoryInfo dinfo = new DirectoryInfo(clientdir); - DirectoryInfo[] Dirs = dinfo.GetDirectories(); - foreach (DirectoryInfo dir in Dirs) - { - if (dir.Name == client) - { - return true; - } } - return false; - } -} -#endregion - -#region Script Functions -public class ScriptFuncs -{ -#region Script Generator/Signer - public class Generator - { - public static void SignGeneratedScript(string scriptFileName, bool newSigFormat = false, bool encodeInBase64 = true) + public static bool IsClientValid(string client) { - string privateKeyPath = Path.GetDirectoryName(scriptFileName) + "//privatekey.txt"; - - if (File.Exists(privateKeyPath)) + string clientdir = GlobalPaths.ClientDir; + DirectoryInfo dinfo = new DirectoryInfo(clientdir); + DirectoryInfo[] Dirs = dinfo.GetDirectories(); + foreach (DirectoryInfo dir in Dirs) { - //init vars - string format = (newSigFormat ? "--rbxsig" : "") + "%{0}%{1}"; - byte[] blob = Encoding.Default.GetBytes(File.ReadAllText(privateKeyPath)); - - if (encodeInBase64) + if (dir.Name == client) { - blob = Convert.FromBase64String(Encoding.Default.GetString(blob)); + return true; } - - //create cryptography providers - var shaCSP = new SHA1CryptoServiceProvider(); - var rsaCSP = new RSACryptoServiceProvider(); - rsaCSP.ImportCspBlob(blob); - - // sign script - string script = "\r\n" + File.ReadAllText(scriptFileName); - byte[] signature = rsaCSP.SignData(Encoding.Default.GetBytes(script), shaCSP); - // override file. - Util.FixedFileDelete(scriptFileName); - File.WriteAllText(scriptFileName, string.Format(format, Convert.ToBase64String(signature), script)); } - else - { - //create the signature file if it doesn't exist - var signingRSACSP = new RSACryptoServiceProvider(1024); - byte[] privateKeyBlob = signingRSACSP.ExportCspBlob(true); - signingRSACSP.Dispose(); - // save our text file in the script's directory - File.WriteAllText(privateKeyPath, encodeInBase64 ? Convert.ToBase64String(privateKeyBlob) : Encoding.Default.GetString(privateKeyBlob)); - - // try signing again. - SignGeneratedScript(scriptFileName, encodeInBase64); - } + return false; } + } + #endregion - public static string GetScriptFuncForType(ScriptType type) + #region Script Functions + public class ScriptFuncs + { + #region Script Generator/Signer + public class Generator { - return GetScriptFuncForType(GlobalVars.UserConfiguration.SelectedClient, type); - } + public static void SignGeneratedScript(string scriptFileName, bool newSigFormat = false, bool encodeInBase64 = true) + { + string privateKeyPath = Path.GetDirectoryName(scriptFileName) + "//privatekey.txt"; - public static string GetScriptFuncForType(string ClientName, ScriptType type) - { - FileFormat.ClientInfo info = ClientManagement.GetClientInfoValues(ClientName); + if (File.Exists(privateKeyPath)) + { + //init vars + string format = (newSigFormat ? "--rbxsig" : "") + "%{0}%{1}"; + byte[] blob = Encoding.Default.GetBytes(File.ReadAllText(privateKeyPath)); - string rbxexe = ""; - if (info.LegacyMode) - { - rbxexe = GlobalPaths.ClientDir + @"\\" + ClientName + @"\\RobloxApp.exe"; + if (encodeInBase64) + { + blob = Convert.FromBase64String(Encoding.Default.GetString(blob)); + } + + //create cryptography providers + var shaCSP = new SHA1CryptoServiceProvider(); + var rsaCSP = new RSACryptoServiceProvider(); + rsaCSP.ImportCspBlob(blob); + + // sign script + string script = "\r\n" + File.ReadAllText(scriptFileName); + byte[] signature = rsaCSP.SignData(Encoding.Default.GetBytes(script), shaCSP); + // override file. + Util.FixedFileDelete(scriptFileName); + File.WriteAllText(scriptFileName, string.Format(format, Convert.ToBase64String(signature), script)); + } + else + { + //create the signature file if it doesn't exist + var signingRSACSP = new RSACryptoServiceProvider(1024); + byte[] privateKeyBlob = signingRSACSP.ExportCspBlob(true); + signingRSACSP.Dispose(); + + // save our text file in the script's directory + File.WriteAllText(privateKeyPath, encodeInBase64 ? Convert.ToBase64String(privateKeyBlob) : Encoding.Default.GetString(privateKeyBlob)); + + // try signing again. + SignGeneratedScript(scriptFileName, encodeInBase64); + } } - else if (info.SeperateFolders) + + public static string GetScriptFuncForType(ScriptType type) { - rbxexe = GlobalPaths.ClientDir + @"\\" + ClientName + @"\\client\\RobloxApp_client.exe"; + return GetScriptFuncForType(GlobalVars.UserConfiguration.SelectedClient, type); } - else if (info.UsesCustomClientEXEName) + + public static string GetScriptFuncForType(string ClientName, ScriptType type) { - rbxexe = GlobalPaths.ClientDir + @"\\" + ClientName + @"\\" + info.CustomClientEXEName; - } - else - { - rbxexe = GlobalPaths.ClientDir + @"\\" + ClientName + @"\\RobloxApp_client.exe"; - } + FileFormat.ClientInfo info = ClientManagement.GetClientInfoValues(ClientName); + + string rbxexe = ""; + if (info.LegacyMode) + { + rbxexe = GlobalPaths.ClientDir + @"\\" + ClientName + @"\\RobloxApp.exe"; + } + else if (info.SeperateFolders) + { + rbxexe = GlobalPaths.ClientDir + @"\\" + ClientName + @"\\client\\RobloxApp_client.exe"; + } + else if (info.UsesCustomClientEXEName) + { + rbxexe = GlobalPaths.ClientDir + @"\\" + ClientName + @"\\" + info.CustomClientEXEName; + } + else + { + rbxexe = GlobalPaths.ClientDir + @"\\" + ClientName + @"\\RobloxApp_client.exe"; + } #if LAUNCHER string md5dir = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(Assembly.GetExecutingAssembly().Location) : ""; #else - string md5dir = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(GlobalPaths.RootPathLauncher + "\\Novetus.exe") : ""; + string md5dir = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(GlobalPaths.RootPathLauncher + "\\Novetus.exe") : ""; #endif - string md5script = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(GlobalPaths.ClientDir + @"\\" + ClientName + @"\\content\\scripts\\" + GlobalPaths.ScriptName + ".lua") : ""; - string md5exe = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(rbxexe) : ""; - string md5s = "'" + md5exe + "','" + md5dir + "','" + md5script + "'"; + string md5script = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(GlobalPaths.ClientDir + @"\\" + ClientName + @"\\content\\scripts\\" + GlobalPaths.ScriptName + ".lua") : ""; + string md5exe = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(rbxexe) : ""; + string md5s = "'" + md5exe + "','" + md5dir + "','" + md5script + "'"; - switch (type) - { - case ScriptType.Client: - return "_G.CSConnect(" - + (info.UsesID ? GlobalVars.UserConfiguration.UserID : 0) + ",'" - + GlobalVars.CurrentServer.ServerIP + "'," - + GlobalVars.CurrentServer.ServerPort + ",'" - + (info.UsesPlayerName ? GlobalVars.UserConfiguration.PlayerName : "Player") + "'," - + GlobalVars.Loadout + "," - + md5s + ",'" - + GlobalVars.PlayerTripcode - + ((GlobalVars.ValidatedExtraFiles > 0) ? "'," + GlobalVars.ValidatedExtraFiles.ToString() + "," : "',0,") - + GlobalVars.UserConfiguration.NewGUI.ToString().ToLower() + ");"; - case ScriptType.Server: - return "_G.CSServer(" - + GlobalVars.UserConfiguration.RobloxPort + "," - + GlobalVars.UserConfiguration.PlayerLimit + "," - + md5s + "," - + GlobalVars.UserConfiguration.ShowServerNotifications.ToString().ToLower() - + ((GlobalVars.ValidatedExtraFiles > 0) ? "," + GlobalVars.ValidatedExtraFiles.ToString() + "," : ",0,") - + GlobalVars.UserConfiguration.NewGUI.ToString().ToLower() + ");"; - case ScriptType.Solo: - case ScriptType.EasterEgg: - return "_G.CSSolo(" - + (info.UsesID ? GlobalVars.UserConfiguration.UserID : 0) + ",'" - + (info.UsesPlayerName ? GlobalVars.UserConfiguration.PlayerName : "Player") + "'," - + GlobalVars.soloLoadout + "," - + GlobalVars.UserConfiguration.NewGUI.ToString().ToLower() + ");"; - case ScriptType.Studio: - return "_G.CSStudio(" - + GlobalVars.UserConfiguration.NewGUI.ToString().ToLower() + ");"; - default: - return ""; + switch (type) + { + case ScriptType.Client: + return "_G.CSConnect(" + + (info.UsesID ? GlobalVars.UserConfiguration.UserID : 0) + ",'" + + GlobalVars.CurrentServer.ServerIP + "'," + + GlobalVars.CurrentServer.ServerPort + ",'" + + (info.UsesPlayerName ? GlobalVars.UserConfiguration.PlayerName : "Player") + "'," + + GlobalVars.Loadout + "," + + md5s + ",'" + + GlobalVars.PlayerTripcode + + ((GlobalVars.ValidatedExtraFiles > 0) ? "'," + GlobalVars.ValidatedExtraFiles.ToString() + "," : "',0,") + + GlobalVars.UserConfiguration.NewGUI.ToString().ToLower() + ");"; + case ScriptType.Server: + return "_G.CSServer(" + + GlobalVars.UserConfiguration.RobloxPort + "," + + GlobalVars.UserConfiguration.PlayerLimit + "," + + md5s + "," + + GlobalVars.UserConfiguration.ShowServerNotifications.ToString().ToLower() + + ((GlobalVars.ValidatedExtraFiles > 0) ? "," + GlobalVars.ValidatedExtraFiles.ToString() + "," : ",0,") + + GlobalVars.UserConfiguration.NewGUI.ToString().ToLower() + ");"; + case ScriptType.Solo: + case ScriptType.EasterEgg: + return "_G.CSSolo(" + + (info.UsesID ? GlobalVars.UserConfiguration.UserID : 0) + ",'" + + (info.UsesPlayerName ? GlobalVars.UserConfiguration.PlayerName : "Player") + "'," + + GlobalVars.soloLoadout + "," + + GlobalVars.UserConfiguration.NewGUI.ToString().ToLower() + ");"; + case ScriptType.Studio: + return "_G.CSStudio(" + + GlobalVars.UserConfiguration.NewGUI.ToString().ToLower() + ");"; + default: + return ""; + } } - } - public static string GetNameForType(ScriptType type) - { - switch (type) + public static string GetNameForType(ScriptType type) { - case ScriptType.Client: - return "Client"; - case ScriptType.Server: - return "Server"; - case ScriptType.Solo: - return "Play Solo"; - case ScriptType.Studio: - return "Studio"; - case ScriptType.EasterEgg: - return "A message from Bitl"; - default: - return "N/A"; + switch (type) + { + case ScriptType.Client: + return "Client"; + case ScriptType.Server: + return "Server"; + case ScriptType.Solo: + return "Play Solo"; + case ScriptType.Studio: + return "Studio"; + case ScriptType.EasterEgg: + return "A message from Bitl"; + default: + return "N/A"; + } } - } - public static void GenerateScriptForClient(ScriptType type) - { - GenerateScriptForClient(GlobalVars.UserConfiguration.SelectedClient, type); - } + public static void GenerateScriptForClient(ScriptType type) + { + GenerateScriptForClient(GlobalVars.UserConfiguration.SelectedClient, type); + } - public static void GenerateScriptForClient(string ClientName, ScriptType type) - { - bool shouldUseLoadFile = GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%useloadfile%"); - string execScriptMethod = shouldUseLoadFile ? "loadfile" : "dofile"; + public static void GenerateScriptForClient(string ClientName, ScriptType type) + { + bool shouldUseLoadFile = GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%useloadfile%"); + string execScriptMethod = shouldUseLoadFile ? "loadfile" : "dofile"; - string[] code = { + string[] code = { "--Load Script", //scriptcontents, (GlobalVars.SelectedClientInfo.SeperateFolders ? "" + @@ -1557,336 +1559,337 @@ public class ScriptFuncs GetScriptFuncForType(type), }; - if (GlobalVars.SelectedClientInfo.SeperateFolders) - { - string scriptsFolder = GlobalPaths.ClientDir + @"\\" + ClientName + @"\\" + ClientManagement.GetClientSeperateFolderName(type) + @"\\content\\scripts"; - if (!Directory.Exists(scriptsFolder)) + if (GlobalVars.SelectedClientInfo.SeperateFolders) { - Directory.CreateDirectory(scriptsFolder); + string scriptsFolder = GlobalPaths.ClientDir + @"\\" + ClientName + @"\\" + ClientManagement.GetClientSeperateFolderName(type) + @"\\content\\scripts"; + if (!Directory.Exists(scriptsFolder)) + { + Directory.CreateDirectory(scriptsFolder); + } + } + + string outputPath = (GlobalVars.SelectedClientInfo.SeperateFolders ? + GlobalPaths.ClientDir + @"\\" + ClientName + @"\\" + ClientManagement.GetClientSeperateFolderName(type) + @"\\content\\scripts\\" + GlobalPaths.ScriptGenName + ".lua" : + GlobalPaths.ClientDir + @"\\" + ClientName + @"\\content\\scripts\\" + GlobalPaths.ScriptGenName + ".lua"); + + File.WriteAllLines(outputPath, code); + + bool shouldSign = GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%signgeneratedjoinscript%"); + bool shouldUseNewSigFormat = GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%usenewsignformat%"); + + if (shouldSign) + { + SignGeneratedScript(outputPath, shouldUseNewSigFormat); } } - string outputPath = (GlobalVars.SelectedClientInfo.SeperateFolders ? - GlobalPaths.ClientDir + @"\\" + ClientName + @"\\" + ClientManagement.GetClientSeperateFolderName(type) + @"\\content\\scripts\\" + GlobalPaths.ScriptGenName + ".lua" : - GlobalPaths.ClientDir + @"\\" + ClientName + @"\\content\\scripts\\" + GlobalPaths.ScriptGenName + ".lua"); - - File.WriteAllLines(outputPath, code); - - bool shouldSign = GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%signgeneratedjoinscript%"); - bool shouldUseNewSigFormat = GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%usenewsignformat%"); - - if (shouldSign) + public static string GetGeneratedScriptName(string ClientName, ScriptType type) { - SignGeneratedScript(outputPath, shouldUseNewSigFormat); + GenerateScriptForClient(ClientName, type); + return ClientManagement.GetGenLuaFileName(ClientName, type); } } + #endregion - public static string GetGeneratedScriptName(string ClientName, ScriptType type) + #region ClientScript Parser + public class ClientScript { - GenerateScriptForClient(ClientName, type); - return ClientManagement.GetGenLuaFileName(ClientName, type); - } - } -#endregion - -#region ClientScript Parser - public class ClientScript - { - public static string GetArgsFromTag(string code, string tag, string endtag) - { - try + public static string GetArgsFromTag(string code, string tag, string endtag) { - if (string.IsNullOrEmpty(endtag)) + try { - //VERSION 2!! - string result = code.Substring(code.IndexOf(tag) + tag.Length); - return result; + if (string.IsNullOrEmpty(endtag)) + { + //VERSION 2!! + string result = code.Substring(code.IndexOf(tag) + tag.Length); + return result; + } + else + { + int pFrom = code.IndexOf(tag) + tag.Length; + int pTo = code.LastIndexOf(endtag); + string result = code.Substring(pFrom, pTo - pFrom); + return result; + } } - else - { - int pFrom = code.IndexOf(tag) + tag.Length; - int pTo = code.LastIndexOf(endtag); - string result = code.Substring(pFrom, pTo - pFrom); - return result; - } - } #if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); + catch (Exception ex) + { + Util.LogExceptions(ex); #else catch (Exception) { #endif - return ""; - } - } - - public static ScriptType GetTypeFromTag(string tag) - { - switch (tag) - { - case string client when client.Contains("client"): - return ScriptType.Client; - case string server when server.Contains("server"): - case string no3d when no3d.Contains("no3d"): - return ScriptType.Server; - case string solo when solo.Contains("solo"): - return ScriptType.Solo; - case string studio when studio.Contains("studio"): - return ScriptType.Studio; - default: - return ScriptType.None; - } - } - - public static string GetTagFromType(ScriptType type, bool endtag, bool no3d, bool v1) - { - if (v1) - { - switch (type) - { - case ScriptType.Client: - return endtag ? "" : ""; - case ScriptType.Server: - return no3d ? (endtag ? "" : "") : (endtag ? "" : ""); - case ScriptType.Solo: - return endtag ? "" : ""; - case ScriptType.Studio: - return endtag ? "" : ""; - default: - return ""; - } - } - else - { - if (endtag == true) - { - //NO END TAGS. return ""; } + } - switch (type) + public static ScriptType GetTypeFromTag(string tag) + { + switch (tag) { - case ScriptType.Client: - return "client="; - case ScriptType.Server: - return no3d ? "no3d=" : "server="; - case ScriptType.Solo: - return "solo="; - case ScriptType.Studio: - return "studio="; + case string client when client.Contains("client"): + return ScriptType.Client; + case string server when server.Contains("server"): + case string no3d when no3d.Contains("no3d"): + return ScriptType.Server; + case string solo when solo.Contains("solo"): + return ScriptType.Solo; + case string studio when studio.Contains("studio"): + return ScriptType.Studio; default: - return ""; - } - } - } - - public static int ConvertIconStringToInt() - { - switch (GlobalVars.UserCustomization.Icon) - { - case "BC": - return 1; - case "TBC": - return 2; - case "OBC": - return 3; - case "NBC": - default: - return 0; - } - } - - public static string GetFolderAndMapName(string source, string seperator) - { - try - { - string result = source.Substring(0, source.IndexOf(seperator)); - - if (File.Exists(GlobalPaths.MapsDir + @"\\" + result + @"\\" + source)) - { - return result + @"\\" + source; - } - else - { - return source; - } - } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif - return source; - } - } - - public static string GetFolderAndMapName(string source) - { - return GetFolderAndMapName(source, " -"); - } - - public static string GetRawArgsForType(ScriptType type, string ClientName, string luafile) - { - FileFormat.ClientInfo info = ClientManagement.GetClientInfoValues(ClientName); - - if (!info.Fix2007) - { - return Generator.GetScriptFuncForType(ClientName, type); - } - else - { - return luafile; - } - } - - public static string CompileScript(string code, string tag, string endtag, string mapfile, string luafile, string rbxexe, bool usesharedtags = true) - { - return CompileScript(GlobalVars.UserConfiguration.SelectedClient, code, tag, endtag, mapfile, luafile, rbxexe, usesharedtags); - } - - public static string CompileScript(string ClientName, string code, string tag, string endtag, string mapfile, string luafile, string rbxexe, bool usesharedtags = true) - { - string start = tag; - string end = endtag; - - bool v1 = false; - - if (code.Contains("<") && - code.Contains("")) - { - v1 = true; - } - else - { - //make sure we have no end tags. - if (!string.IsNullOrWhiteSpace(end)) - { - end = ""; + return ScriptType.None; } } - FileFormat.ClientInfo info = ClientManagement.GetClientInfoValues(ClientName); - - ScriptType type = GetTypeFromTag(start); - - //we must have the ending tag before we continue. - if (v1 && string.IsNullOrWhiteSpace(end)) - { - return ""; - } - - if (usesharedtags) + public static string GetTagFromType(ScriptType type, bool endtag, bool no3d, bool v1) { if (v1) { - string sharedstart = ""; - string sharedend = ""; - - if (code.Contains(sharedstart) && code.Contains(sharedend)) + switch (type) { - start = sharedstart; - end = sharedend; + case ScriptType.Client: + return endtag ? "" : ""; + case ScriptType.Server: + return no3d ? (endtag ? "" : "") : (endtag ? "" : ""); + case ScriptType.Solo: + return endtag ? "" : ""; + case ScriptType.Studio: + return endtag ? "" : ""; + default: + return ""; } } else { - string sharedstart = "shared="; - - if (code.Contains(sharedstart)) + if (endtag == true) { - start = sharedstart; + //NO END TAGS. + return ""; + } + + switch (type) + { + case ScriptType.Client: + return "client="; + case ScriptType.Server: + return no3d ? "no3d=" : "server="; + case ScriptType.Solo: + return "solo="; + case ScriptType.Studio: + return "studio="; + default: + return ""; } } } - if (info.Fix2007) + public static int ConvertIconStringToInt() { - Generator.GenerateScriptForClient(type); + switch (GlobalVars.UserCustomization.Icon) + { + case "BC": + return 1; + case "TBC": + return 2; + case "OBC": + return 3; + case "NBC": + default: + return 0; + } } - string extractedCode = GetArgsFromTag(code, start, end); + public static string GetFolderAndMapName(string source, string seperator) + { + try + { + string result = source.Substring(0, source.IndexOf(seperator)); + + if (File.Exists(GlobalPaths.MapsDir + @"\\" + result + @"\\" + source)) + { + return result + @"\\" + source; + } + else + { + return source; + } + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); +#else + catch (Exception) + { +#endif + return source; + } + } + + public static string GetFolderAndMapName(string source) + { + return GetFolderAndMapName(source, " -"); + } + + public static string GetRawArgsForType(ScriptType type, string ClientName, string luafile) + { + FileFormat.ClientInfo info = ClientManagement.GetClientInfoValues(ClientName); + + if (!info.Fix2007) + { + return Generator.GetScriptFuncForType(ClientName, type); + } + else + { + return luafile; + } + } + + public static string CompileScript(string code, string tag, string endtag, string mapfile, string luafile, string rbxexe, bool usesharedtags = true) + { + return CompileScript(GlobalVars.UserConfiguration.SelectedClient, code, tag, endtag, mapfile, luafile, rbxexe, usesharedtags); + } + + public static string CompileScript(string ClientName, string code, string tag, string endtag, string mapfile, string luafile, string rbxexe, bool usesharedtags = true) + { + string start = tag; + string end = endtag; + + bool v1 = false; + + if (code.Contains("<") && + code.Contains("")) + { + v1 = true; + } + else + { + //make sure we have no end tags. + if (!string.IsNullOrWhiteSpace(end)) + { + end = ""; + } + } + + FileFormat.ClientInfo info = ClientManagement.GetClientInfoValues(ClientName); + + ScriptType type = GetTypeFromTag(start); + + //we must have the ending tag before we continue. + if (v1 && string.IsNullOrWhiteSpace(end)) + { + return ""; + } + + if (usesharedtags) + { + if (v1) + { + string sharedstart = ""; + string sharedend = ""; + + if (code.Contains(sharedstart) && code.Contains(sharedend)) + { + start = sharedstart; + end = sharedend; + } + } + else + { + string sharedstart = "shared="; + + if (code.Contains(sharedstart)) + { + start = sharedstart; + } + } + } + + if (info.Fix2007) + { + Generator.GenerateScriptForClient(type); + } + + string extractedCode = GetArgsFromTag(code, start, end); #if LAUNCHER string md5dir = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(Assembly.GetExecutingAssembly().Location) : ""; #else - string md5dir = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(GlobalPaths.RootPathLauncher + "\\Novetus.exe") : ""; + string md5dir = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(GlobalPaths.RootPathLauncher + "\\Novetus.exe") : ""; #endif - string md5script = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(GlobalPaths.ClientDir + @"\\" + GlobalVars.UserConfiguration.SelectedClient + @"\\content\\scripts\\" + GlobalPaths.ScriptName + ".lua") : ""; - string md5exe = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(rbxexe) : ""; - string md5sd = "'" + md5exe + "','" + md5dir + "','" + md5script + "'"; - string md5s = "'" + info.ClientMD5 + "','" + md5dir + "','" + info.ScriptMD5 + "'"; - string compiled = extractedCode.Replace("%version%", GlobalVars.ProgramInformation.Version) - .Replace("%mapfile%", mapfile) - .Replace("%luafile%", luafile) - .Replace("%charapp%", GlobalVars.UserCustomization.CharacterID) - .Replace("%server%", GlobalVars.CurrentServer.ToString()) - .Replace("%ip%", GlobalVars.CurrentServer.ServerIP) - .Replace("%port%", GlobalVars.UserConfiguration.RobloxPort.ToString()) - .Replace("%joinport%", GlobalVars.CurrentServer.ServerPort.ToString()) - .Replace("%name%", GlobalVars.UserConfiguration.PlayerName) - .Replace("%icone%", ConvertIconStringToInt().ToString()) - .Replace("%icon%", GlobalVars.UserCustomization.Icon) - .Replace("%id%", GlobalVars.UserConfiguration.UserID.ToString()) - .Replace("%face%", GlobalVars.UserCustomization.Face) - .Replace("%head%", GlobalVars.UserCustomization.Head) - .Replace("%tshirt%", GlobalVars.UserCustomization.TShirt) - .Replace("%shirt%", GlobalVars.UserCustomization.Shirt) - .Replace("%pants%", GlobalVars.UserCustomization.Pants) - .Replace("%hat1%", GlobalVars.UserCustomization.Hat1) - .Replace("%hat2%", GlobalVars.UserCustomization.Hat2) - .Replace("%hat3%", GlobalVars.UserCustomization.Hat3) - .Replace("%faced%", GlobalVars.UserCustomization.Face.Contains("http://") ? GlobalVars.UserCustomization.Face : GlobalPaths.faceGameDir + GlobalVars.UserCustomization.Face) - .Replace("%headd%", GlobalPaths.headGameDir + GlobalVars.UserCustomization.Head) - .Replace("%tshirtd%", GlobalVars.UserCustomization.TShirt.Contains("http://") ? GlobalVars.UserCustomization.TShirt : GlobalPaths.tshirtGameDir + GlobalVars.UserCustomization.TShirt) - .Replace("%shirtd%", GlobalVars.UserCustomization.Shirt.Contains("http://") ? GlobalVars.UserCustomization.Shirt : GlobalPaths.shirtGameDir + GlobalVars.UserCustomization.Shirt) - .Replace("%pantsd%", GlobalVars.UserCustomization.Pants.Contains("http://") ? GlobalVars.UserCustomization.Pants : GlobalPaths.pantsGameDir + GlobalVars.UserCustomization.Pants) - .Replace("%hat1d%", GlobalPaths.hatGameDir + GlobalVars.UserCustomization.Hat1) - .Replace("%hat2d%", GlobalPaths.hatGameDir + GlobalVars.UserCustomization.Hat2) - .Replace("%hat3d%", GlobalPaths.hatGameDir + GlobalVars.UserCustomization.Hat3) - .Replace("%headcolor%", GlobalVars.UserCustomization.HeadColorID.ToString()) - .Replace("%torsocolor%", GlobalVars.UserCustomization.TorsoColorID.ToString()) - .Replace("%larmcolor%", GlobalVars.UserCustomization.LeftArmColorID.ToString()) - .Replace("%llegcolor%", GlobalVars.UserCustomization.LeftLegColorID.ToString()) - .Replace("%rarmcolor%", GlobalVars.UserCustomization.RightArmColorID.ToString()) - .Replace("%rlegcolor%", GlobalVars.UserCustomization.RightLegColorID.ToString()) - .Replace("%md5launcher%", md5dir) - .Replace("%md5script%", info.ScriptMD5) - .Replace("%md5exe%", info.ClientMD5) - .Replace("%md5scriptd%", md5script) - .Replace("%md5exed%", md5exe) - .Replace("%md5s%", md5s) - .Replace("%md5sd%", md5sd) - .Replace("%limit%", GlobalVars.UserConfiguration.PlayerLimit.ToString()) - .Replace("%extra%", GlobalVars.UserCustomization.Extra) - .Replace("%hat4%", GlobalVars.UserCustomization.Extra) - .Replace("%extrad%", GlobalPaths.extraGameDir + GlobalVars.UserCustomization.Extra) - .Replace("%hat4d%", GlobalPaths.hatGameDir + GlobalVars.UserCustomization.Extra) - .Replace("%mapfiled%", GlobalPaths.BaseGameDir + GlobalVars.UserConfiguration.MapPathSnip.Replace(@"\\", @"\").Replace(@"/", @"\")) - .Replace("%mapfilec%", extractedCode.Contains("%mapfilec%") ? NovetusFuncs.CopyMapToRBXAsset() : "") - .Replace("%tripcode%", GlobalVars.PlayerTripcode) - .Replace("%scripttype%", Generator.GetNameForType(type)) - .Replace("%notifications%", GlobalVars.UserConfiguration.ShowServerNotifications.ToString().ToLower()) - .Replace("%loadout%", code.Contains("") ? GlobalVars.soloLoadout : GlobalVars.Loadout) - .Replace("%validatedextrafiles%", GlobalVars.ValidatedExtraFiles.ToString()) - .Replace("%argstring%", GetRawArgsForType(type, ClientName, luafile)) - .Replace("%tshirttexid%", GlobalVars.TShirtTextureID) - .Replace("%shirttexid%", GlobalVars.ShirtTextureID) - .Replace("%pantstexid%", GlobalVars.PantsTextureID) - .Replace("%facetexid%", GlobalVars.FaceTextureID) - .Replace("%tshirttexidlocal%", GlobalVars.TShirtTextureLocal) - .Replace("%shirttexidlocal%", GlobalVars.ShirtTextureLocal) - .Replace("%pantstexidlocal%", GlobalVars.PantsTextureLocal) - .Replace("%facetexlocal%", GlobalVars.FaceTextureLocal) - .Replace("%newgui%", GlobalVars.UserConfiguration.NewGUI.ToString().ToLower()); + string md5script = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(GlobalPaths.ClientDir + @"\\" + GlobalVars.UserConfiguration.SelectedClient + @"\\content\\scripts\\" + GlobalPaths.ScriptName + ".lua") : ""; + string md5exe = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(rbxexe) : ""; + string md5sd = "'" + md5exe + "','" + md5dir + "','" + md5script + "'"; + string md5s = "'" + info.ClientMD5 + "','" + md5dir + "','" + info.ScriptMD5 + "'"; + string compiled = extractedCode.Replace("%version%", GlobalVars.ProgramInformation.Version) + .Replace("%mapfile%", mapfile) + .Replace("%luafile%", luafile) + .Replace("%charapp%", GlobalVars.UserCustomization.CharacterID) + .Replace("%server%", GlobalVars.CurrentServer.ToString()) + .Replace("%ip%", GlobalVars.CurrentServer.ServerIP) + .Replace("%port%", GlobalVars.UserConfiguration.RobloxPort.ToString()) + .Replace("%joinport%", GlobalVars.CurrentServer.ServerPort.ToString()) + .Replace("%name%", GlobalVars.UserConfiguration.PlayerName) + .Replace("%icone%", ConvertIconStringToInt().ToString()) + .Replace("%icon%", GlobalVars.UserCustomization.Icon) + .Replace("%id%", GlobalVars.UserConfiguration.UserID.ToString()) + .Replace("%face%", GlobalVars.UserCustomization.Face) + .Replace("%head%", GlobalVars.UserCustomization.Head) + .Replace("%tshirt%", GlobalVars.UserCustomization.TShirt) + .Replace("%shirt%", GlobalVars.UserCustomization.Shirt) + .Replace("%pants%", GlobalVars.UserCustomization.Pants) + .Replace("%hat1%", GlobalVars.UserCustomization.Hat1) + .Replace("%hat2%", GlobalVars.UserCustomization.Hat2) + .Replace("%hat3%", GlobalVars.UserCustomization.Hat3) + .Replace("%faced%", GlobalVars.UserCustomization.Face.Contains("http://") ? GlobalVars.UserCustomization.Face : GlobalPaths.faceGameDir + GlobalVars.UserCustomization.Face) + .Replace("%headd%", GlobalPaths.headGameDir + GlobalVars.UserCustomization.Head) + .Replace("%tshirtd%", GlobalVars.UserCustomization.TShirt.Contains("http://") ? GlobalVars.UserCustomization.TShirt : GlobalPaths.tshirtGameDir + GlobalVars.UserCustomization.TShirt) + .Replace("%shirtd%", GlobalVars.UserCustomization.Shirt.Contains("http://") ? GlobalVars.UserCustomization.Shirt : GlobalPaths.shirtGameDir + GlobalVars.UserCustomization.Shirt) + .Replace("%pantsd%", GlobalVars.UserCustomization.Pants.Contains("http://") ? GlobalVars.UserCustomization.Pants : GlobalPaths.pantsGameDir + GlobalVars.UserCustomization.Pants) + .Replace("%hat1d%", GlobalPaths.hatGameDir + GlobalVars.UserCustomization.Hat1) + .Replace("%hat2d%", GlobalPaths.hatGameDir + GlobalVars.UserCustomization.Hat2) + .Replace("%hat3d%", GlobalPaths.hatGameDir + GlobalVars.UserCustomization.Hat3) + .Replace("%headcolor%", GlobalVars.UserCustomization.HeadColorID.ToString()) + .Replace("%torsocolor%", GlobalVars.UserCustomization.TorsoColorID.ToString()) + .Replace("%larmcolor%", GlobalVars.UserCustomization.LeftArmColorID.ToString()) + .Replace("%llegcolor%", GlobalVars.UserCustomization.LeftLegColorID.ToString()) + .Replace("%rarmcolor%", GlobalVars.UserCustomization.RightArmColorID.ToString()) + .Replace("%rlegcolor%", GlobalVars.UserCustomization.RightLegColorID.ToString()) + .Replace("%md5launcher%", md5dir) + .Replace("%md5script%", info.ScriptMD5) + .Replace("%md5exe%", info.ClientMD5) + .Replace("%md5scriptd%", md5script) + .Replace("%md5exed%", md5exe) + .Replace("%md5s%", md5s) + .Replace("%md5sd%", md5sd) + .Replace("%limit%", GlobalVars.UserConfiguration.PlayerLimit.ToString()) + .Replace("%extra%", GlobalVars.UserCustomization.Extra) + .Replace("%hat4%", GlobalVars.UserCustomization.Extra) + .Replace("%extrad%", GlobalPaths.extraGameDir + GlobalVars.UserCustomization.Extra) + .Replace("%hat4d%", GlobalPaths.hatGameDir + GlobalVars.UserCustomization.Extra) + .Replace("%mapfiled%", GlobalPaths.BaseGameDir + GlobalVars.UserConfiguration.MapPathSnip.Replace(@"\\", @"\").Replace(@"/", @"\")) + .Replace("%mapfilec%", extractedCode.Contains("%mapfilec%") ? NovetusFuncs.CopyMapToRBXAsset() : "") + .Replace("%tripcode%", GlobalVars.PlayerTripcode) + .Replace("%scripttype%", Generator.GetNameForType(type)) + .Replace("%notifications%", GlobalVars.UserConfiguration.ShowServerNotifications.ToString().ToLower()) + .Replace("%loadout%", code.Contains("") ? GlobalVars.soloLoadout : GlobalVars.Loadout) + .Replace("%validatedextrafiles%", GlobalVars.ValidatedExtraFiles.ToString()) + .Replace("%argstring%", GetRawArgsForType(type, ClientName, luafile)) + .Replace("%tshirttexid%", GlobalVars.TShirtTextureID) + .Replace("%shirttexid%", GlobalVars.ShirtTextureID) + .Replace("%pantstexid%", GlobalVars.PantsTextureID) + .Replace("%facetexid%", GlobalVars.FaceTextureID) + .Replace("%tshirttexidlocal%", GlobalVars.TShirtTextureLocal) + .Replace("%shirttexidlocal%", GlobalVars.ShirtTextureLocal) + .Replace("%pantstexidlocal%", GlobalVars.PantsTextureLocal) + .Replace("%facetexlocal%", GlobalVars.FaceTextureLocal) + .Replace("%newgui%", GlobalVars.UserConfiguration.NewGUI.ToString().ToLower()); - return compiled; + return compiled; + } } + #endregion } -#endregion + #endregion } -#endregion diff --git a/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs b/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs index 024a61f..7f0821b 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs @@ -14,1237 +14,947 @@ using System.Xml.Serialization; using System.Runtime.Versioning; #endregion -#region File Formats -public class FileFormat +namespace Novetus.Core { - #region Client Information - public class ClientInfo + #region File Formats + public class FileFormat { - public ClientInfo() + #region Client Information + public class ClientInfo { - UsesPlayerName = true; - UsesID = true; - Description = ""; - Warning = ""; - LegacyMode = false; - ClientMD5 = ""; - ScriptMD5 = ""; - Fix2007 = false; - AlreadyHasSecurity = false; - ClientLoadOptions = Settings.ClientLoadOptions.Client_2008AndUp; - SeperateFolders = false; - UsesCustomClientEXEName = false; - CustomClientEXEName = ""; - CommandLineArgs = "%args%"; + public ClientInfo() + { + UsesPlayerName = true; + UsesID = true; + Description = ""; + Warning = ""; + LegacyMode = false; + ClientMD5 = ""; + ScriptMD5 = ""; + Fix2007 = false; + AlreadyHasSecurity = false; + ClientLoadOptions = Settings.ClientLoadOptions.Client_2008AndUp; + SeperateFolders = false; + UsesCustomClientEXEName = false; + CustomClientEXEName = ""; + CommandLineArgs = "%args%"; + } + + public bool UsesPlayerName { get; set; } + public bool UsesID { get; set; } + public string Description { get; set; } + public string Warning { get; set; } + public bool LegacyMode { get; set; } + public string ClientMD5 { get; set; } + public string ScriptMD5 { get; set; } + public bool Fix2007 { get; set; } + public bool AlreadyHasSecurity { get; set; } + public bool SeperateFolders { get; set; } + public bool UsesCustomClientEXEName { get; set; } + public string CustomClientEXEName { get; set; } + public Settings.ClientLoadOptions ClientLoadOptions { get; set; } + public string CommandLineArgs { get; set; } } + #endregion - public bool UsesPlayerName { get; set; } - public bool UsesID { get; set; } - public string Description { get; set; } - public string Warning { get; set; } - public bool LegacyMode { get; set; } - public string ClientMD5 { get; set; } - public string ScriptMD5 { get; set; } - public bool Fix2007 { get; set; } - public bool AlreadyHasSecurity { get; set; } - public bool SeperateFolders { get; set; } - public bool UsesCustomClientEXEName { get; set; } - public string CustomClientEXEName { get; set; } - public Settings.ClientLoadOptions ClientLoadOptions { get; set; } - public string CommandLineArgs { get; set; } - } - #endregion - - #region Configuration - public class Config - { - public Config() + #region Configuration + public class Config { - SelectedClient = ""; - Map = ""; - CloseOnLaunch = false; - UserID = 0; - PlayerName = "Player"; - RobloxPort = 53640; - PlayerLimit = 12; - UPnP = false; - DisabledAssetSDKHelp = false; - DiscordPresence = true; - MapPath = ""; - MapPathSnip = ""; - GraphicsMode = Settings.Mode.Automatic; - ReShade = false; - QualityLevel = Settings.Level.Automatic; - LauncherStyle = Settings.Style.Stylish; - ReShadeFPSDisplay = false; - ReShadePerformanceMode = false; - AssetSDKFixerSaveBackups = true; - AlternateServerIP = ""; - DisableReshadeDelete = false; - ShowServerNotifications = false; - ServerBrowserServerName = "Novetus"; - ServerBrowserServerAddress = "localhost"; - Priority = ProcessPriorityClass.RealTime; - FirstServerLaunch = true; - NewGUI = false; - URIQuickConfigure = true; - BootstrapperShowUI = true; - WebProxyInitialSetupRequired = true; - WebProxyEnabled = false; + public Config() + { + SelectedClient = ""; + Map = ""; + CloseOnLaunch = false; + UserID = 0; + PlayerName = "Player"; + RobloxPort = 53640; + PlayerLimit = 12; + UPnP = false; + DisabledAssetSDKHelp = false; + DiscordPresence = true; + MapPath = ""; + MapPathSnip = ""; + GraphicsMode = Settings.Mode.Automatic; + ReShade = false; + QualityLevel = Settings.Level.Automatic; + LauncherStyle = Settings.Style.Stylish; + ReShadeFPSDisplay = false; + ReShadePerformanceMode = false; + AssetSDKFixerSaveBackups = true; + AlternateServerIP = ""; + DisableReshadeDelete = false; + ShowServerNotifications = false; + ServerBrowserServerName = "Novetus"; + ServerBrowserServerAddress = "localhost"; + Priority = ProcessPriorityClass.RealTime; + FirstServerLaunch = true; + NewGUI = false; + URIQuickConfigure = true; + BootstrapperShowUI = true; + WebProxyInitialSetupRequired = true; + WebProxyEnabled = false; + } + + public string SelectedClient { get; set; } + public string Map { get; set; } + public bool CloseOnLaunch { get; set; } + public int UserID { get; set; } + public string PlayerName { get; set; } + public int RobloxPort { get; set; } + public int PlayerLimit { get; set; } + public bool UPnP { get; set; } + public bool DisabledAssetSDKHelp { get; set; } + public bool DiscordPresence { get; set; } + public string MapPath { get; set; } + public string MapPathSnip { get; set; } + public Settings.Mode GraphicsMode { get; set; } + public bool ReShade { get; set; } + public Settings.Level QualityLevel { get; set; } + public Settings.Style LauncherStyle { get; set; } + public bool ReShadeFPSDisplay { get; set; } + public bool ReShadePerformanceMode { get; set; } + public bool AssetSDKFixerSaveBackups { get; set; } + public string AlternateServerIP { get; set; } + public bool DisableReshadeDelete { get; set; } + public bool ShowServerNotifications { get; set; } + public string ServerBrowserServerName { get; set; } + public string ServerBrowserServerAddress { get; set; } + public ProcessPriorityClass Priority { get; set; } + public bool FirstServerLaunch { get; set; } + public bool NewGUI { get; set; } + public bool URIQuickConfigure { get; set; } + public bool BootstrapperShowUI { get; set; } + public bool WebProxyInitialSetupRequired { get; set; } + public bool WebProxyEnabled { get; set; } } + #endregion - public string SelectedClient { get; set; } - public string Map { get; set; } - public bool CloseOnLaunch { get; set; } - public int UserID { get; set; } - public string PlayerName { get; set; } - public int RobloxPort { get; set; } - public int PlayerLimit { get; set; } - public bool UPnP { get; set; } - public bool DisabledAssetSDKHelp { get; set; } - public bool DiscordPresence { get; set; } - public string MapPath { get; set; } - public string MapPathSnip { get; set; } - public Settings.Mode GraphicsMode { get; set; } - public bool ReShade { get; set; } - public Settings.Level QualityLevel { get; set; } - public Settings.Style LauncherStyle { get; set; } - public bool ReShadeFPSDisplay { get; set; } - public bool ReShadePerformanceMode { get; set; } - public bool AssetSDKFixerSaveBackups { get; set; } - public string AlternateServerIP { get; set; } - public bool DisableReshadeDelete { get; set; } - public bool ShowServerNotifications { get; set; } - public string ServerBrowserServerName { get; set; } - public string ServerBrowserServerAddress { get; set; } - public ProcessPriorityClass Priority { get; set; } - public bool FirstServerLaunch { get; set; } - public bool NewGUI { get; set; } - public bool URIQuickConfigure { get; set; } - public bool BootstrapperShowUI { get; set; } - public bool WebProxyInitialSetupRequired { get; set; } - public bool WebProxyEnabled { get; set; } - } - #endregion - - #region Customization Configuration - public class CustomizationConfig - { - public CustomizationConfig() + #region Customization Configuration + public class CustomizationConfig { - Hat1 = "NoHat.rbxm"; - Hat2 = "NoHat.rbxm"; - Hat3 = "NoHat.rbxm"; - Face = "DefaultFace.rbxm"; - Head = "DefaultHead.rbxm"; - TShirt = "NoTShirt.rbxm"; - Shirt = "NoShirt.rbxm"; - Pants = "NoPants.rbxm"; - Icon = "NBC"; - Extra = "NoExtra.rbxm"; - HeadColorID = 24; - TorsoColorID = 23; - LeftArmColorID = 24; - RightArmColorID = 24; - LeftLegColorID = 119; - RightLegColorID = 119; - HeadColorString = "Color [A=255, R=245, G=205, B=47]"; - TorsoColorString = "Color [A=255, R=13, G=105, B=172]"; - LeftArmColorString = "Color [A=255, R=245, G=205, B=47]"; - RightArmColorString = "Color [A=255, R=245, G=205, B=47]"; - LeftLegColorString = "Color [A=255, R=164, G=189, B=71]"; - RightLegColorString = "Color [A=255, R=164, G=189, B=71]"; - ExtraSelectionIsHat = false; - ShowHatsInExtra = false; - CharacterID = ""; + public CustomizationConfig() + { + Hat1 = "NoHat.rbxm"; + Hat2 = "NoHat.rbxm"; + Hat3 = "NoHat.rbxm"; + Face = "DefaultFace.rbxm"; + Head = "DefaultHead.rbxm"; + TShirt = "NoTShirt.rbxm"; + Shirt = "NoShirt.rbxm"; + Pants = "NoPants.rbxm"; + Icon = "NBC"; + Extra = "NoExtra.rbxm"; + HeadColorID = 24; + TorsoColorID = 23; + LeftArmColorID = 24; + RightArmColorID = 24; + LeftLegColorID = 119; + RightLegColorID = 119; + HeadColorString = "Color [A=255, R=245, G=205, B=47]"; + TorsoColorString = "Color [A=255, R=13, G=105, B=172]"; + LeftArmColorString = "Color [A=255, R=245, G=205, B=47]"; + RightArmColorString = "Color [A=255, R=245, G=205, B=47]"; + LeftLegColorString = "Color [A=255, R=164, G=189, B=71]"; + RightLegColorString = "Color [A=255, R=164, G=189, B=71]"; + ExtraSelectionIsHat = false; + ShowHatsInExtra = false; + CharacterID = ""; + } + + public string Hat1 { get; set; } + public string Hat2 { get; set; } + public string Hat3 { get; set; } + public string Face { get; set; } + public string Head { get; set; } + public string TShirt { get; set; } + public string Shirt { get; set; } + public string Pants { get; set; } + public string Icon { get; set; } + public string Extra { get; set; } + public int HeadColorID { get; set; } + public int TorsoColorID { get; set; } + public int LeftArmColorID { get; set; } + public int RightArmColorID { get; set; } + public int LeftLegColorID { get; set; } + public int RightLegColorID { get; set; } + public string HeadColorString { get; set; } + public string TorsoColorString { get; set; } + public string LeftArmColorString { get; set; } + public string RightArmColorString { get; set; } + public string LeftLegColorString { get; set; } + public string RightLegColorString { get; set; } + public bool ExtraSelectionIsHat { get; set; } + public bool ShowHatsInExtra { get; set; } + public string CharacterID { get; set; } } + #endregion - public string Hat1 { get; set; } - public string Hat2 { get; set; } - public string Hat3 { get; set; } - public string Face { get; set; } - public string Head { get; set; } - public string TShirt { get; set; } - public string Shirt { get; set; } - public string Pants { get; set; } - public string Icon { get; set; } - public string Extra { get; set; } - public int HeadColorID { get; set; } - public int TorsoColorID { get; set; } - public int LeftArmColorID { get; set; } - public int RightArmColorID { get; set; } - public int LeftLegColorID { get; set; } - public int RightLegColorID { get; set; } - public string HeadColorString { get; set; } - public string TorsoColorString { get; set; } - public string LeftArmColorString { get; set; } - public string RightArmColorString { get; set; } - public string LeftLegColorString { get; set; } - public string RightLegColorString { get; set; } - public bool ExtraSelectionIsHat { get; set; } - public bool ShowHatsInExtra { get; set; } - public string CharacterID { get; set; } - } - #endregion - - #region Program Information - public class ProgramInfo - { - public ProgramInfo() + #region Program Information + public class ProgramInfo { - Version = ""; - Branch = ""; - DefaultClient = ""; - RegisterClient1 = ""; - RegisterClient2 = ""; - DefaultMap = ""; - //HACK + public ProgramInfo() + { + Version = ""; + Branch = ""; + DefaultClient = ""; + RegisterClient1 = ""; + RegisterClient2 = ""; + DefaultMap = ""; + //HACK #if NET4 NetVersion = ".NET 4.0"; #elif NET481 - NetVersion = ".NET 4.8"; + NetVersion = ".NET 4.8"; #endif - InitialBootup = true; - } + InitialBootup = true; + } - public string Version { get; set; } - public string Branch { get; set; } - public string DefaultClient { get; set; } - public string RegisterClient1 { get; set; } - public string RegisterClient2 { get; set; } - public string DefaultMap { get; set; } - public string NetVersion { get; set; } - public bool InitialBootup { get; set; } + public string Version { get; set; } + public string Branch { get; set; } + public string DefaultClient { get; set; } + public string RegisterClient1 { get; set; } + public string RegisterClient2 { get; set; } + public string DefaultMap { get; set; } + public string NetVersion { get; set; } + public bool InitialBootup { get; set; } + } + #endregion } #endregion -} -#endregion -#region Part Color Options -public class PartColor -{ - public string ColorName; - public int ColorID; - public string ColorRGB; - [XmlIgnore] - public Color ColorObject; - [XmlIgnore] - public string ColorGroup; - [XmlIgnore] - public string ColorRawName; - [XmlIgnore] - public Bitmap ColorImage; -} - -[XmlRoot("PartColors")] -public class PartColors -{ - [XmlArray("ColorList")] - public PartColor[] ColorList; -} - -public class PartColorLoader -{ - public static PartColor[] GetPartColors() + #region Part Color Options + public class PartColor { - if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.PartColorXMLName)) + public string ColorName; + public int ColorID; + public string ColorRGB; + [XmlIgnore] + public Color ColorObject; + [XmlIgnore] + public string ColorGroup; + [XmlIgnore] + public string ColorRawName; + [XmlIgnore] + public Bitmap ColorImage; + } + + [XmlRoot("PartColors")] + public class PartColors + { + [XmlArray("ColorList")] + public PartColor[] ColorList; + } + + public class PartColorLoader + { + public static PartColor[] GetPartColors() { - XmlSerializer serializer = new XmlSerializer(typeof(PartColors)); - PartColors colors; - - using (FileStream fs = new FileStream(GlobalPaths.ConfigDir + "\\" + GlobalPaths.PartColorXMLName, FileMode.Open)) + if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.PartColorXMLName)) { - colors = (PartColors)serializer.Deserialize(fs); - } + XmlSerializer serializer = new XmlSerializer(typeof(PartColors)); + PartColors colors; - foreach (var item in colors.ColorList) - { - string colorFixed = Regex.Replace(item.ColorRGB, @"[\[\]\{\}\(\)\<\> ]", ""); - string[] rgbValues = colorFixed.Split(','); - item.ColorObject = Color.FromArgb(Convert.ToInt32(rgbValues[0]), Convert.ToInt32(rgbValues[1]), Convert.ToInt32(rgbValues[2])); - - if (!(item.ColorName.Contains("[") && item.ColorName.Contains("]"))) + using (FileStream fs = new FileStream(GlobalPaths.ConfigDir + "\\" + GlobalPaths.PartColorXMLName, FileMode.Open)) { - item.ColorRawName = item.ColorName; - item.ColorName = "[Uncategorized]" + item.ColorName; - } - else - { - item.ColorRawName = item.ColorName; + colors = (PartColors)serializer.Deserialize(fs); } - int pFrom = item.ColorName.IndexOf("["); - int pTo = item.ColorName.IndexOf("]"); - item.ColorGroup = item.ColorName.Substring(pFrom + 1, pTo - pFrom - 1); - item.ColorName = item.ColorName.Replace(item.ColorGroup, "").Replace("[", "").Replace("]", ""); - item.ColorImage = GeneratePartColorIcon(item, 128); - } - - return colors.ColorList; - } - else - { - return null; - } - } - - //make faster - public static void AddPartColorsToListView(PartColor[] PartColorList, ListView ColorView, int imgsize, bool showIDs = false) - { - try - { - ImageList ColorImageList = new ImageList(); - ColorImageList.ImageSize = new Size(imgsize, imgsize); - ColorImageList.ColorDepth = ColorDepth.Depth32Bit; - ColorView.LargeImageList = ColorImageList; - ColorView.SmallImageList = ColorImageList; - - foreach (var item in PartColorList) - { - var lvi = new ListViewItem(item.ColorName); - lvi.Tag = item.ColorID; - - if (showIDs) + foreach (var item in colors.ColorList) { - lvi.Text = lvi.Text + " (" + item.ColorID + ")"; - } + string colorFixed = Regex.Replace(item.ColorRGB, @"[\[\]\{\}\(\)\<\> ]", ""); + string[] rgbValues = colorFixed.Split(','); + item.ColorObject = Color.FromArgb(Convert.ToInt32(rgbValues[0]), Convert.ToInt32(rgbValues[1]), Convert.ToInt32(rgbValues[2])); - var group = ColorView.Groups.Cast().FirstOrDefault(g => g.Header == item.ColorGroup); - - if (group == null) - { - group = new ListViewGroup(item.ColorGroup); - ColorView.Groups.Add(group); - } - - lvi.Group = group; - - if (item.ColorImage != null) - { - ColorImageList.Images.Add(item.ColorName, item.ColorImage); - lvi.ImageIndex = ColorImageList.Images.IndexOfKey(item.ColorName); - } - - ColorView.Items.Add(lvi); - } - - /*foreach (var group in ColorView.Groups.Cast()) - { - group.Header = group.Header + " (" + group.Items.Count + ")"; - }*/ - } -#if URI || LAUNCHER || CMD || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif - } - } - - public static Bitmap GeneratePartColorIcon(PartColor color, int imgsize) - { - try - { - Bitmap Bmp = new Bitmap(imgsize, imgsize, PixelFormat.Format32bppArgb); - using (Graphics gfx = Graphics.FromImage(Bmp)) - using (SolidBrush brush = new SolidBrush(color.ColorObject)) - { - gfx.FillRectangle(brush, 0, 0, imgsize, imgsize); - } - - return Bmp; - } -#if URI || LAUNCHER || CMD || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif - return null; - } - } - - public static PartColor FindPartColorByName(PartColor[] colors, string query) - { - if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.PartColorXMLName)) - { - return colors.SingleOrDefault(item => query.Contains(item.ColorName)); - } - else - { - return null; - } - } - - public static PartColor FindPartColorByID(PartColor[] colors, string query) - { - if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.PartColorXMLName)) - { - return colors.SingleOrDefault(item => query.Contains(item.ColorID.ToString())); - } - else - { - return null; - } - } -} -#endregion - -#region Content Provider Options -public class Provider -{ - public string Name; - public string URL; - public string Icon; -} - -[XmlRoot("ContentProviders")] -public class ContentProviders -{ - [XmlArray("Providers")] - public Provider[] Providers; -} - -public class OnlineClothing -{ - public static Provider[] GetContentProviders() - { - if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ContentProviderXMLName)) - { - XmlSerializer serializer = new XmlSerializer(typeof(ContentProviders)); - ContentProviders providers; - - using (FileStream fs = new FileStream(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ContentProviderXMLName, FileMode.Open)) - { - providers = (ContentProviders)serializer.Deserialize(fs); - } - - return providers.Providers; - } - else - { - return null; - } - } - - public static Provider FindContentProviderByName(Provider[] providers, string query) - { - if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ContentProviderXMLName)) - { - return providers.SingleOrDefault(item => query.Contains(item.Name)); - } - else - { - return null; - } - } - - public static Provider FindContentProviderByURL(Provider[] providers, string query) - { - if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ContentProviderXMLName)) - { - return providers.SingleOrDefault(item => query.Contains(item.URL)); - } - else - { - return null; - } - } -} -#endregion - -#region Settings -public class Settings -{ - public enum Mode - { - Automatic = 0, - OpenGLStable = 1, - OpenGLExperimental = 2, - DirectX = 3 - } - - public enum Level - { - Automatic = 0, - VeryLow = 1, - Low = 2, - Medium = 3, - High = 4, - Ultra = 5, - Custom = 6 - } - - public enum Style - { - None = 0, - Extended = 1, - Compact = 2, - Stylish = 3 - } - - public enum ClientLoadOptions - { - Client_2007_NoGraphicsOptions = 0, - Client_2007 = 1, - Client_2008AndUp = 2, - Client_2008AndUp_LegacyOpenGL = 3, - Client_2008AndUp_QualityLevel21 = 4, - Client_2008AndUp_NoGraphicsOptions = 5, - Client_2008AndUp_ForceAutomatic = 6, - Client_2008AndUp_ForceAutomaticQL21 = 7, - Client_2008AndUp_HasCharacterOnlyShadowsLegacyOpenGL = 8 - } - - public static ClientLoadOptions GetClientLoadOptionsForBool(bool level) - { - switch (level) - { - case false: - return ClientLoadOptions.Client_2008AndUp; - default: - return ClientLoadOptions.Client_2007_NoGraphicsOptions; - } - } - - public static string GetPathForClientLoadOptions(ClientLoadOptions level) - { - string localAppdataRobloxPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Roblox"; - string appdataRobloxPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\Roblox"; - - if (!Directory.Exists(localAppdataRobloxPath)) - { - Directory.CreateDirectory(localAppdataRobloxPath); - } - - if (!Directory.Exists(appdataRobloxPath)) - { - Directory.CreateDirectory(appdataRobloxPath); - } - - switch (level) - { - case ClientLoadOptions.Client_2008AndUp_QualityLevel21: - case ClientLoadOptions.Client_2008AndUp_LegacyOpenGL: - case ClientLoadOptions.Client_2008AndUp_NoGraphicsOptions: - case ClientLoadOptions.Client_2008AndUp_ForceAutomatic: - case ClientLoadOptions.Client_2008AndUp_ForceAutomaticQL21: - case ClientLoadOptions.Client_2008AndUp_HasCharacterOnlyShadowsLegacyOpenGL: - case ClientLoadOptions.Client_2008AndUp: - return localAppdataRobloxPath; - default: - return appdataRobloxPath; - } - } -} - -#endregion - -#region Icon Loader - -public class IconLoader -{ - private OpenFileDialog openFileDialog1; - private string installOutcome = ""; - public bool CopyToItemDir = false; - public string ItemDir = ""; - public string ItemName = ""; - public string ItemPath = ""; - - public IconLoader() - { - openFileDialog1 = new OpenFileDialog() - { - FileName = "Select an icon .png file", - Filter = "Portable Network Graphics image (*.png)|*.png", - Title = "Open icon .png" - }; - } - - public void setInstallOutcome(string text) - { - installOutcome = text; - } - - public string getInstallOutcome() - { - return installOutcome; - } - - public void LoadImage() - { - string ItemNameFixed = ItemName.Replace(" ", ""); - string dir = CopyToItemDir ? ItemDir + "\\" + ItemNameFixed : GlobalPaths.extradir + "\\icons\\" + GlobalVars.UserConfiguration.PlayerName; - - if (openFileDialog1.ShowDialog() == DialogResult.OK) - { - try - { - Util.FixedFileCopy(openFileDialog1.FileName, dir + ".png", true); - - if (CopyToItemDir) - { - ItemPath = ItemDir + "\\" + ItemNameFixed + ".png"; - } - - installOutcome = "Icon " + openFileDialog1.SafeFileName + " installed!"; - } - catch (Exception ex) - { - installOutcome = "Error when installing icon: " + ex.Message; -#if URI || LAUNCHER || BASICLAUNCHER - Util.LogExceptions(ex); -#endif - } - } - } -} -#endregion - -#region File Management -public class FileManagement -{ - public static void ReadInfoFile(string infopath, bool other = false, string exepath = "") - { - //READ - string versionbranch, defaultclient, defaultmap, regclient1, - regclient2, extendedversionnumber, extendedversiontemplate, - extendedversionrevision, extendedversioneditchangelog, isLite, - initialBootup; - - INIFile ini = new INIFile(infopath); - - string section = "ProgramInfo"; - - //not using the GlobalVars definitions as those are empty until we fill them in. - versionbranch = ini.IniReadValue(section, "Branch", "0.0"); - defaultclient = ini.IniReadValue(section, "DefaultClient", "2009E"); - defaultmap = ini.IniReadValue(section, "DefaultMap", "Dev - Baseplate2048.rbxl"); - regclient1 = ini.IniReadValue(section, "UserAgentRegisterClient1", "2007M"); - regclient2 = ini.IniReadValue(section, "UserAgentRegisterClient2", "2009L"); - extendedversionnumber = ini.IniReadValue(section, "ExtendedVersionNumber", "False"); - extendedversioneditchangelog = ini.IniReadValue(section, "ExtendedVersionEditChangelog", "False"); - extendedversiontemplate = ini.IniReadValue(section, "ExtendedVersionTemplate", "%version%"); - extendedversionrevision = ini.IniReadValue(section, "ExtendedVersionRevision", "-1"); - isLite = ini.IniReadValue(section, "IsLite", "False"); - initialBootup = ini.IniReadValue(section, "InitialBootup", "True"); - - try - { - GlobalVars.ExtendedVersionNumber = Convert.ToBoolean(extendedversionnumber); - if (GlobalVars.ExtendedVersionNumber) - { - if (other) - { - if (!string.IsNullOrWhiteSpace(exepath)) + if (!(item.ColorName.Contains("[") && item.ColorName.Contains("]"))) { - var versionInfo = FileVersionInfo.GetVersionInfo(exepath); - GlobalVars.ProgramInformation.Version = extendedversiontemplate.Replace("%version%", versionbranch) - .Replace("%build%", versionInfo.ProductBuildPart.ToString()) - .Replace("%revision%", versionInfo.FilePrivatePart.ToString()) - .Replace("%extended-revision%", (!extendedversionrevision.Equals("-1") ? extendedversionrevision : "")); + item.ColorRawName = item.ColorName; + item.ColorName = "[Uncategorized]" + item.ColorName; } else { - return; + item.ColorRawName = item.ColorName; } - } - else - { - GlobalVars.ProgramInformation.Version = extendedversiontemplate.Replace("%version%", versionbranch) - .Replace("%build%", Assembly.GetExecutingAssembly().GetName().Version.Build.ToString()) - .Replace("%revision%", Assembly.GetExecutingAssembly().GetName().Version.Revision.ToString()) - .Replace("%extended-revision%", (!extendedversionrevision.Equals("-1") ? extendedversionrevision : "")); + + int pFrom = item.ColorName.IndexOf("["); + int pTo = item.ColorName.IndexOf("]"); + item.ColorGroup = item.ColorName.Substring(pFrom + 1, pTo - pFrom - 1); + item.ColorName = item.ColorName.Replace(item.ColorGroup, "").Replace("[", "").Replace("]", ""); + item.ColorImage = GeneratePartColorIcon(item, 128); } - bool changelogedit = Convert.ToBoolean(extendedversioneditchangelog); + return colors.ColorList; + } + else + { + return null; + } + } - if (changelogedit) + //make faster + public static void AddPartColorsToListView(PartColor[] PartColorList, ListView ColorView, int imgsize, bool showIDs = false) + { + try + { + ImageList ColorImageList = new ImageList(); + ColorImageList.ImageSize = new Size(imgsize, imgsize); + ColorImageList.ColorDepth = ColorDepth.Depth32Bit; + ColorView.LargeImageList = ColorImageList; + ColorView.SmallImageList = ColorImageList; + + foreach (var item in PartColorList) { - string changelog = GlobalPaths.BasePath + "\\changelog.txt"; - if (File.Exists(changelog)) + var lvi = new ListViewItem(item.ColorName); + lvi.Tag = item.ColorID; + + if (showIDs) { - string[] changeloglines = File.ReadAllLines(changelog); - if (!changeloglines[0].Equals(GlobalVars.ProgramInformation.Version)) + lvi.Text = lvi.Text + " (" + item.ColorID + ")"; + } + + var group = ColorView.Groups.Cast().FirstOrDefault(g => g.Header == item.ColorGroup); + + if (group == null) + { + group = new ListViewGroup(item.ColorGroup); + ColorView.Groups.Add(group); + } + + lvi.Group = group; + + if (item.ColorImage != null) + { + ColorImageList.Images.Add(item.ColorName, item.ColorImage); + lvi.ImageIndex = ColorImageList.Images.IndexOfKey(item.ColorName); + } + + ColorView.Items.Add(lvi); + } + + /*foreach (var group in ColorView.Groups.Cast()) + { + group.Header = group.Header + " (" + group.Items.Count + ")"; + }*/ + } +#if URI || LAUNCHER || CMD || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); +#else + catch (Exception) + { +#endif + } + } + + public static Bitmap GeneratePartColorIcon(PartColor color, int imgsize) + { + try + { + Bitmap Bmp = new Bitmap(imgsize, imgsize, PixelFormat.Format32bppArgb); + using (Graphics gfx = Graphics.FromImage(Bmp)) + using (SolidBrush brush = new SolidBrush(color.ColorObject)) + { + gfx.FillRectangle(brush, 0, 0, imgsize, imgsize); + } + + return Bmp; + } +#if URI || LAUNCHER || CMD || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); +#else + catch (Exception) + { +#endif + return null; + } + } + + public static PartColor FindPartColorByName(PartColor[] colors, string query) + { + if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.PartColorXMLName)) + { + return colors.SingleOrDefault(item => query.Contains(item.ColorName)); + } + else + { + return null; + } + } + + public static PartColor FindPartColorByID(PartColor[] colors, string query) + { + if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.PartColorXMLName)) + { + return colors.SingleOrDefault(item => query.Contains(item.ColorID.ToString())); + } + else + { + return null; + } + } + } + #endregion + + #region Content Provider Options + public class Provider + { + public string Name; + public string URL; + public string Icon; + } + + [XmlRoot("ContentProviders")] + public class ContentProviders + { + [XmlArray("Providers")] + public Provider[] Providers; + } + + public class OnlineClothing + { + public static Provider[] GetContentProviders() + { + if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ContentProviderXMLName)) + { + XmlSerializer serializer = new XmlSerializer(typeof(ContentProviders)); + ContentProviders providers; + + using (FileStream fs = new FileStream(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ContentProviderXMLName, FileMode.Open)) + { + providers = (ContentProviders)serializer.Deserialize(fs); + } + + return providers.Providers; + } + else + { + return null; + } + } + + public static Provider FindContentProviderByName(Provider[] providers, string query) + { + if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ContentProviderXMLName)) + { + return providers.SingleOrDefault(item => query.Contains(item.Name)); + } + else + { + return null; + } + } + + public static Provider FindContentProviderByURL(Provider[] providers, string query) + { + if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ContentProviderXMLName)) + { + return providers.SingleOrDefault(item => query.Contains(item.URL)); + } + else + { + return null; + } + } + } + #endregion + + #region Settings + public class Settings + { + public enum Mode + { + Automatic = 0, + OpenGLStable = 1, + OpenGLExperimental = 2, + DirectX = 3 + } + + public enum Level + { + Automatic = 0, + VeryLow = 1, + Low = 2, + Medium = 3, + High = 4, + Ultra = 5, + Custom = 6 + } + + public enum Style + { + None = 0, + Extended = 1, + Compact = 2, + Stylish = 3 + } + + public enum ClientLoadOptions + { + Client_2007_NoGraphicsOptions = 0, + Client_2007 = 1, + Client_2008AndUp = 2, + Client_2008AndUp_LegacyOpenGL = 3, + Client_2008AndUp_QualityLevel21 = 4, + Client_2008AndUp_NoGraphicsOptions = 5, + Client_2008AndUp_ForceAutomatic = 6, + Client_2008AndUp_ForceAutomaticQL21 = 7, + Client_2008AndUp_HasCharacterOnlyShadowsLegacyOpenGL = 8 + } + + public static ClientLoadOptions GetClientLoadOptionsForBool(bool level) + { + switch (level) + { + case false: + return ClientLoadOptions.Client_2008AndUp; + default: + return ClientLoadOptions.Client_2007_NoGraphicsOptions; + } + } + + public static string GetPathForClientLoadOptions(ClientLoadOptions level) + { + string localAppdataRobloxPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Roblox"; + string appdataRobloxPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\Roblox"; + + if (!Directory.Exists(localAppdataRobloxPath)) + { + Directory.CreateDirectory(localAppdataRobloxPath); + } + + if (!Directory.Exists(appdataRobloxPath)) + { + Directory.CreateDirectory(appdataRobloxPath); + } + + switch (level) + { + case ClientLoadOptions.Client_2008AndUp_QualityLevel21: + case ClientLoadOptions.Client_2008AndUp_LegacyOpenGL: + case ClientLoadOptions.Client_2008AndUp_NoGraphicsOptions: + case ClientLoadOptions.Client_2008AndUp_ForceAutomatic: + case ClientLoadOptions.Client_2008AndUp_ForceAutomaticQL21: + case ClientLoadOptions.Client_2008AndUp_HasCharacterOnlyShadowsLegacyOpenGL: + case ClientLoadOptions.Client_2008AndUp: + return localAppdataRobloxPath; + default: + return appdataRobloxPath; + } + } + } + + #endregion + + #region Icon Loader + + public class IconLoader + { + private OpenFileDialog openFileDialog1; + private string installOutcome = ""; + public bool CopyToItemDir = false; + public string ItemDir = ""; + public string ItemName = ""; + public string ItemPath = ""; + + public IconLoader() + { + openFileDialog1 = new OpenFileDialog() + { + FileName = "Select an icon .png file", + Filter = "Portable Network Graphics image (*.png)|*.png", + Title = "Open icon .png" + }; + } + + public void setInstallOutcome(string text) + { + installOutcome = text; + } + + public string getInstallOutcome() + { + return installOutcome; + } + + public void LoadImage() + { + string ItemNameFixed = ItemName.Replace(" ", ""); + string dir = CopyToItemDir ? ItemDir + "\\" + ItemNameFixed : GlobalPaths.extradir + "\\icons\\" + GlobalVars.UserConfiguration.PlayerName; + + if (openFileDialog1.ShowDialog() == DialogResult.OK) + { + try + { + Util.FixedFileCopy(openFileDialog1.FileName, dir + ".png", true); + + if (CopyToItemDir) + { + ItemPath = ItemDir + "\\" + ItemNameFixed + ".png"; + } + + installOutcome = "Icon " + openFileDialog1.SafeFileName + " installed!"; + } + catch (Exception ex) + { + installOutcome = "Error when installing icon: " + ex.Message; +#if URI || LAUNCHER || BASICLAUNCHER + Util.LogExceptions(ex); +#endif + } + } + } + } + #endregion + + #region File Management + public class FileManagement + { + public static void ReadInfoFile(string infopath, bool other = false, string exepath = "") + { + //READ + string versionbranch, defaultclient, defaultmap, regclient1, + regclient2, extendedversionnumber, extendedversiontemplate, + extendedversionrevision, extendedversioneditchangelog, isLite, + initialBootup; + + INIFile ini = new INIFile(infopath); + + string section = "ProgramInfo"; + + //not using the GlobalVars definitions as those are empty until we fill them in. + versionbranch = ini.IniReadValue(section, "Branch", "0.0"); + defaultclient = ini.IniReadValue(section, "DefaultClient", "2009E"); + defaultmap = ini.IniReadValue(section, "DefaultMap", "Dev - Baseplate2048.rbxl"); + regclient1 = ini.IniReadValue(section, "UserAgentRegisterClient1", "2007M"); + regclient2 = ini.IniReadValue(section, "UserAgentRegisterClient2", "2009L"); + extendedversionnumber = ini.IniReadValue(section, "ExtendedVersionNumber", "False"); + extendedversioneditchangelog = ini.IniReadValue(section, "ExtendedVersionEditChangelog", "False"); + extendedversiontemplate = ini.IniReadValue(section, "ExtendedVersionTemplate", "%version%"); + extendedversionrevision = ini.IniReadValue(section, "ExtendedVersionRevision", "-1"); + isLite = ini.IniReadValue(section, "IsLite", "False"); + initialBootup = ini.IniReadValue(section, "InitialBootup", "True"); + + try + { + GlobalVars.ExtendedVersionNumber = Convert.ToBoolean(extendedversionnumber); + if (GlobalVars.ExtendedVersionNumber) + { + if (other) + { + if (!string.IsNullOrWhiteSpace(exepath)) { - changeloglines[0] = GlobalVars.ProgramInformation.Version; - File.WriteAllLines(changelog, changeloglines); + var versionInfo = FileVersionInfo.GetVersionInfo(exepath); + GlobalVars.ProgramInformation.Version = extendedversiontemplate.Replace("%version%", versionbranch) + .Replace("%build%", versionInfo.ProductBuildPart.ToString()) + .Replace("%revision%", versionInfo.FilePrivatePart.ToString()) + .Replace("%extended-revision%", (!extendedversionrevision.Equals("-1") ? extendedversionrevision : "")); + } + else + { + return; + } + } + else + { + GlobalVars.ProgramInformation.Version = extendedversiontemplate.Replace("%version%", versionbranch) + .Replace("%build%", Assembly.GetExecutingAssembly().GetName().Version.Build.ToString()) + .Replace("%revision%", Assembly.GetExecutingAssembly().GetName().Version.Revision.ToString()) + .Replace("%extended-revision%", (!extendedversionrevision.Equals("-1") ? extendedversionrevision : "")); + } + + bool changelogedit = Convert.ToBoolean(extendedversioneditchangelog); + + if (changelogedit) + { + string changelog = GlobalPaths.BasePath + "\\changelog.txt"; + if (File.Exists(changelog)) + { + string[] changeloglines = File.ReadAllLines(changelog); + if (!changeloglines[0].Equals(GlobalVars.ProgramInformation.Version)) + { + changeloglines[0] = GlobalVars.ProgramInformation.Version; + File.WriteAllLines(changelog, changeloglines); + } } } } - } - else - { - GlobalVars.ProgramInformation.Version = versionbranch; - } + else + { + GlobalVars.ProgramInformation.Version = versionbranch; + } - GlobalVars.ProgramInformation.Branch = versionbranch; - GlobalVars.ProgramInformation.DefaultClient = defaultclient; - GlobalVars.ProgramInformation.DefaultMap = defaultmap; - GlobalVars.ProgramInformation.RegisterClient1 = regclient1; - GlobalVars.ProgramInformation.RegisterClient2 = regclient2; - GlobalVars.ProgramInformation.InitialBootup = Convert.ToBoolean(initialBootup); - GlobalVars.UserConfiguration.SelectedClient = GlobalVars.ProgramInformation.DefaultClient; - GlobalVars.UserConfiguration.Map = GlobalVars.ProgramInformation.DefaultMap; - GlobalVars.UserConfiguration.MapPath = GlobalPaths.MapsDir + @"\\" + GlobalVars.ProgramInformation.DefaultMap; - GlobalVars.UserConfiguration.MapPathSnip = GlobalPaths.MapsDirBase + @"\\" + GlobalVars.ProgramInformation.DefaultMap; - } + GlobalVars.ProgramInformation.Branch = versionbranch; + GlobalVars.ProgramInformation.DefaultClient = defaultclient; + GlobalVars.ProgramInformation.DefaultMap = defaultmap; + GlobalVars.ProgramInformation.RegisterClient1 = regclient1; + GlobalVars.ProgramInformation.RegisterClient2 = regclient2; + GlobalVars.ProgramInformation.InitialBootup = Convert.ToBoolean(initialBootup); + GlobalVars.UserConfiguration.SelectedClient = GlobalVars.ProgramInformation.DefaultClient; + GlobalVars.UserConfiguration.Map = GlobalVars.ProgramInformation.DefaultMap; + GlobalVars.UserConfiguration.MapPath = GlobalPaths.MapsDir + @"\\" + GlobalVars.ProgramInformation.DefaultMap; + GlobalVars.UserConfiguration.MapPathSnip = GlobalPaths.MapsDirBase + @"\\" + GlobalVars.ProgramInformation.DefaultMap; + } #if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); + catch (Exception ex) + { + Util.LogExceptions(ex); #else catch (Exception) { #endif - ReadInfoFile(infopath, other); + ReadInfoFile(infopath, other); + } } - } - public static void TurnOffInitialSequence() - { - //READ - INIFile ini = new INIFile(GlobalPaths.ConfigDir + "\\" + GlobalPaths.InfoName); - string section = "ProgramInfo"; - - string initialBootup = ini.IniReadValue(section, "InitialBootup", "True"); - if (Convert.ToBoolean(initialBootup) == true) + public static void TurnOffInitialSequence() { - ini.IniWriteValue(section, "InitialBootup", "False"); - } - } + //READ + INIFile ini = new INIFile(GlobalPaths.ConfigDir + "\\" + GlobalPaths.InfoName); + string section = "ProgramInfo"; - public static string ConfigUseOldValIfExists(INIFile ini, string section, string oldKey, string newKey, string val, bool write) - { - if (write) - { - if (!ini.IniValueExists(newKey)) + string initialBootup = ini.IniReadValue(section, "InitialBootup", "True"); + if (Convert.ToBoolean(initialBootup) == true) { - if (GlobalVars.ProgramInformation.InitialBootup) + ini.IniWriteValue(section, "InitialBootup", "False"); + } + } + + public static string ConfigUseOldValIfExists(INIFile ini, string section, string oldKey, string newKey, string val, bool write) + { + if (write) + { + if (!ini.IniValueExists(newKey)) { - if (ini.IniValueExists(oldKey)) + if (GlobalVars.ProgramInformation.InitialBootup) { - ini.IniWriteValue(section, oldKey, val); + if (ini.IniValueExists(oldKey)) + { + ini.IniWriteValue(section, oldKey, val); + } + else + { + ini.IniWriteValue(section, newKey, val); + } } else { - ini.IniWriteValue(section, newKey, val); + ini.IniWriteValue(section, oldKey, val); } } else { - ini.IniWriteValue(section, oldKey, val); + ini.IniWriteValue(section, newKey, val); + } + + return ""; + } + else + { + if (ini.IniValueExists(newKey)) + { + return ini.IniReadValue(section, newKey, val); + } + else + { + return ini.IniReadValue(section, oldKey, val); } } - else - { - ini.IniWriteValue(section, newKey, val); - } - - return ""; } - else + + private static int ValueInt(string val, int defaultVal) { - if (ini.IniValueExists(newKey)) + int res; + if (int.TryParse(val, out res)) { - return ini.IniReadValue(section, newKey, val); + return Convert.ToInt32(val); } else { - return ini.IniReadValue(section, oldKey, val); + return defaultVal; } } - } - private static int ValueInt(string val, int defaultVal) - { - int res; - if (int.TryParse(val, out res)) + private static bool ValueBool(string val, bool defaultVal) { - return Convert.ToInt32(val); - } - else - { - return defaultVal; - } - } - - private static bool ValueBool(string val, bool defaultVal) - { - bool res; - if (bool.TryParse(val, out res)) - { - return Convert.ToBoolean(val); - } - else - { - return defaultVal; - } - } - - public static void Config(string cfgpath, bool write, bool doubleCheck = false) - { - bool forcewrite = false; - - if (!File.Exists(cfgpath)) - { - // force write mode on if the file doesn't exist. - write = true; - forcewrite = true; - } - - if (write) - { - if (Util.IsWineRunning()) + bool res; + if (bool.TryParse(val, out res)) { - GlobalVars.UserConfiguration.LauncherStyle = Settings.Style.Extended; + return Convert.ToBoolean(val); } - - //WRITE - INIFile ini = new INIFile(cfgpath); - - string section = "Config"; - - ini.IniWriteValue(section, "CloseOnLaunch", GlobalVars.UserConfiguration.CloseOnLaunch.ToString()); - ini.IniWriteValue(section, "UserID", GlobalVars.UserConfiguration.UserID.ToString()); - ini.IniWriteValue(section, "PlayerName", GlobalVars.UserConfiguration.PlayerName.ToString()); - ini.IniWriteValue(section, "SelectedClient", GlobalVars.UserConfiguration.SelectedClient.ToString()); - ini.IniWriteValue(section, "Map", GlobalVars.UserConfiguration.Map.ToString()); - ini.IniWriteValue(section, "RobloxPort", GlobalVars.UserConfiguration.RobloxPort.ToString()); - ini.IniWriteValue(section, "PlayerLimit", GlobalVars.UserConfiguration.PlayerLimit.ToString()); - ini.IniWriteValue(section, "UPnP", GlobalVars.UserConfiguration.UPnP.ToString()); - ini.IniWriteValue(section, "DiscordRichPresence", GlobalVars.UserConfiguration.DiscordPresence.ToString()); - ini.IniWriteValue(section, "MapPath", GlobalVars.UserConfiguration.MapPath.ToString()); - ini.IniWriteValue(section, "MapPathSnip", GlobalVars.UserConfiguration.MapPathSnip.ToString()); - ini.IniWriteValue(section, "GraphicsMode", ((int)GlobalVars.UserConfiguration.GraphicsMode).ToString()); - ini.IniWriteValue(section, "ReShade", GlobalVars.UserConfiguration.ReShade.ToString()); - ini.IniWriteValue(section, "QualityLevel", ((int)GlobalVars.UserConfiguration.QualityLevel).ToString()); - ini.IniWriteValue(section, "Style", ((int)GlobalVars.UserConfiguration.LauncherStyle).ToString()); - ini.IniWriteValue(section, "AlternateServerIP", GlobalVars.UserConfiguration.AlternateServerIP.ToString()); - ini.IniWriteValue(section, "DisableReshadeDelete", GlobalVars.UserConfiguration.DisableReshadeDelete.ToString()); - ini.IniWriteValue(section, "ShowServerNotifications", GlobalVars.UserConfiguration.ShowServerNotifications.ToString()); - ini.IniWriteValue(section, "ServerBrowserServerName", GlobalVars.UserConfiguration.ServerBrowserServerName.ToString()); - ini.IniWriteValue(section, "ServerBrowserServerAddress", GlobalVars.UserConfiguration.ServerBrowserServerAddress.ToString()); - ini.IniWriteValue(section, "ClientLaunchPriority", ((int)GlobalVars.UserConfiguration.Priority).ToString()); - ini.IniWriteValue(section, "FirstServerLaunch", GlobalVars.UserConfiguration.FirstServerLaunch.ToString()); - ini.IniWriteValue(section, "NewGUI", GlobalVars.UserConfiguration.NewGUI.ToString()); - ini.IniWriteValue(section, "URIQuickConfigure", GlobalVars.UserConfiguration.URIQuickConfigure.ToString()); - ini.IniWriteValue(section, "BootstrapperShowUI", GlobalVars.UserConfiguration.BootstrapperShowUI.ToString()); - ini.IniWriteValue(section, "WebProxyInitialSetupRequired", GlobalVars.UserConfiguration.WebProxyInitialSetupRequired.ToString()); - ini.IniWriteValue(section, "WebProxyEnabled", GlobalVars.UserConfiguration.WebProxyEnabled.ToString()); - ConfigUseOldValIfExists(ini, section, "ItemMakerDisableHelpMessage", "AssetSDKDisableHelpMessage", GlobalVars.UserConfiguration.DisabledAssetSDKHelp.ToString(), write); - ConfigUseOldValIfExists(ini, section, "AssetLocalizerSaveBackups", "AssetSDKFixerSaveBackups", GlobalVars.UserConfiguration.AssetSDKFixerSaveBackups.ToString(), write); - - if (forcewrite) + else { - // try again.... - Config(cfgpath, false, doubleCheck); + return defaultVal; } } - else - { - try - { - //READ - string closeonlaunch, userid, name, selectedclient, - map, port, limit, upnp, - disablehelpmessage, discord, mappath, mapsnip, - graphics, reshade, qualitylevel, style, savebackups, altIP, - disReshadeDel, showNotifs, SB_Name, SB_Address, priority, - firstServerLaunch, newgui, quickconfigure, bootstrapper, - webproxysetup, webproxy; + public static void Config(string cfgpath, bool write, bool doubleCheck = false) + { + bool forcewrite = false; + + if (!File.Exists(cfgpath)) + { + // force write mode on if the file doesn't exist. + write = true; + forcewrite = true; + } + + if (write) + { + if (Util.IsWineRunning()) + { + GlobalVars.UserConfiguration.LauncherStyle = Settings.Style.Extended; + } + + //WRITE INIFile ini = new INIFile(cfgpath); string section = "Config"; - closeonlaunch = ini.IniReadValue(section, "CloseOnLaunch", GlobalVars.UserConfiguration.CloseOnLaunch.ToString()); - userid = ini.IniReadValue(section, "UserID", GlobalVars.UserConfiguration.UserID.ToString()); - name = ini.IniReadValue(section, "PlayerName", GlobalVars.UserConfiguration.PlayerName.ToString()); - selectedclient = ini.IniReadValue(section, "SelectedClient", GlobalVars.UserConfiguration.SelectedClient.ToString()); - map = ini.IniReadValue(section, "Map", GlobalVars.UserConfiguration.Map.ToString()); - port = ini.IniReadValue(section, "RobloxPort", GlobalVars.UserConfiguration.RobloxPort.ToString()); - limit = ini.IniReadValue(section, "PlayerLimit", GlobalVars.UserConfiguration.PlayerLimit.ToString()); - upnp = ini.IniReadValue(section, "UPnP", GlobalVars.UserConfiguration.UPnP.ToString()); - discord = ini.IniReadValue(section, "DiscordRichPresence", GlobalVars.UserConfiguration.DiscordPresence.ToString()); - mappath = ini.IniReadValue(section, "MapPath", GlobalVars.UserConfiguration.MapPath.ToString()); - mapsnip = ini.IniReadValue(section, "MapPathSnip", GlobalVars.UserConfiguration.MapPathSnip.ToString()); - graphics = ini.IniReadValue(section, "GraphicsMode", ((int)GlobalVars.UserConfiguration.GraphicsMode).ToString()); - reshade = ini.IniReadValue(section, "ReShade", GlobalVars.UserConfiguration.ReShade.ToString()); - qualitylevel = ini.IniReadValue(section, "QualityLevel", ((int)GlobalVars.UserConfiguration.QualityLevel).ToString()); - style = ini.IniReadValue(section, "Style", ((int)GlobalVars.UserConfiguration.LauncherStyle).ToString()); - altIP = ini.IniReadValue(section, "AlternateServerIP", GlobalVars.UserConfiguration.AlternateServerIP.ToString()); - disReshadeDel = ini.IniReadValue(section, "DisableReshadeDelete", GlobalVars.UserConfiguration.DisableReshadeDelete.ToString()); - showNotifs = ini.IniReadValue(section, "ShowServerNotifications", GlobalVars.UserConfiguration.ShowServerNotifications.ToString()); - SB_Name = ini.IniReadValue(section, "ServerBrowserServerName", GlobalVars.UserConfiguration.ServerBrowserServerName.ToString()); - SB_Address = ini.IniReadValue(section, "ServerBrowserServerAddress", GlobalVars.UserConfiguration.ServerBrowserServerAddress.ToString()); - priority = ini.IniReadValue(section, "ClientLaunchPriority", ((int)GlobalVars.UserConfiguration.Priority).ToString()); - firstServerLaunch = ini.IniReadValue(section, "FirstServerLaunch", GlobalVars.UserConfiguration.FirstServerLaunch.ToString()); - newgui = ini.IniReadValue(section, "NewGUI", GlobalVars.UserConfiguration.NewGUI.ToString()); - quickconfigure = ini.IniReadValue(section, "URIQuickConfigure", GlobalVars.UserConfiguration.URIQuickConfigure.ToString()); - bootstrapper = ini.IniReadValue(section, "BootstrapperShowUI", GlobalVars.UserConfiguration.BootstrapperShowUI.ToString()); - webproxysetup = ini.IniReadValue(section, "WebProxyInitialSetupRequired", GlobalVars.UserConfiguration.WebProxyInitialSetupRequired.ToString()); - webproxy = ini.IniReadValue(section, "WebProxyEnabled", GlobalVars.UserConfiguration.WebProxyEnabled.ToString()); - disablehelpmessage = ConfigUseOldValIfExists(ini, section, "ItemMakerDisableHelpMessage", "AssetSDKDisableHelpMessage", GlobalVars.UserConfiguration.DisabledAssetSDKHelp.ToString(), write); - savebackups = ConfigUseOldValIfExists(ini, section, "AssetLocalizerSaveBackups", "AssetSDKFixerSaveBackups", GlobalVars.UserConfiguration.AssetSDKFixerSaveBackups.ToString(), write); + ini.IniWriteValue(section, "CloseOnLaunch", GlobalVars.UserConfiguration.CloseOnLaunch.ToString()); + ini.IniWriteValue(section, "UserID", GlobalVars.UserConfiguration.UserID.ToString()); + ini.IniWriteValue(section, "PlayerName", GlobalVars.UserConfiguration.PlayerName.ToString()); + ini.IniWriteValue(section, "SelectedClient", GlobalVars.UserConfiguration.SelectedClient.ToString()); + ini.IniWriteValue(section, "Map", GlobalVars.UserConfiguration.Map.ToString()); + ini.IniWriteValue(section, "RobloxPort", GlobalVars.UserConfiguration.RobloxPort.ToString()); + ini.IniWriteValue(section, "PlayerLimit", GlobalVars.UserConfiguration.PlayerLimit.ToString()); + ini.IniWriteValue(section, "UPnP", GlobalVars.UserConfiguration.UPnP.ToString()); + ini.IniWriteValue(section, "DiscordRichPresence", GlobalVars.UserConfiguration.DiscordPresence.ToString()); + ini.IniWriteValue(section, "MapPath", GlobalVars.UserConfiguration.MapPath.ToString()); + ini.IniWriteValue(section, "MapPathSnip", GlobalVars.UserConfiguration.MapPathSnip.ToString()); + ini.IniWriteValue(section, "GraphicsMode", ((int)GlobalVars.UserConfiguration.GraphicsMode).ToString()); + ini.IniWriteValue(section, "ReShade", GlobalVars.UserConfiguration.ReShade.ToString()); + ini.IniWriteValue(section, "QualityLevel", ((int)GlobalVars.UserConfiguration.QualityLevel).ToString()); + ini.IniWriteValue(section, "Style", ((int)GlobalVars.UserConfiguration.LauncherStyle).ToString()); + ini.IniWriteValue(section, "AlternateServerIP", GlobalVars.UserConfiguration.AlternateServerIP.ToString()); + ini.IniWriteValue(section, "DisableReshadeDelete", GlobalVars.UserConfiguration.DisableReshadeDelete.ToString()); + ini.IniWriteValue(section, "ShowServerNotifications", GlobalVars.UserConfiguration.ShowServerNotifications.ToString()); + ini.IniWriteValue(section, "ServerBrowserServerName", GlobalVars.UserConfiguration.ServerBrowserServerName.ToString()); + ini.IniWriteValue(section, "ServerBrowserServerAddress", GlobalVars.UserConfiguration.ServerBrowserServerAddress.ToString()); + ini.IniWriteValue(section, "ClientLaunchPriority", ((int)GlobalVars.UserConfiguration.Priority).ToString()); + ini.IniWriteValue(section, "FirstServerLaunch", GlobalVars.UserConfiguration.FirstServerLaunch.ToString()); + ini.IniWriteValue(section, "NewGUI", GlobalVars.UserConfiguration.NewGUI.ToString()); + ini.IniWriteValue(section, "URIQuickConfigure", GlobalVars.UserConfiguration.URIQuickConfigure.ToString()); + ini.IniWriteValue(section, "BootstrapperShowUI", GlobalVars.UserConfiguration.BootstrapperShowUI.ToString()); + ini.IniWriteValue(section, "WebProxyInitialSetupRequired", GlobalVars.UserConfiguration.WebProxyInitialSetupRequired.ToString()); + ini.IniWriteValue(section, "WebProxyEnabled", GlobalVars.UserConfiguration.WebProxyEnabled.ToString()); + ConfigUseOldValIfExists(ini, section, "ItemMakerDisableHelpMessage", "AssetSDKDisableHelpMessage", GlobalVars.UserConfiguration.DisabledAssetSDKHelp.ToString(), write); + ConfigUseOldValIfExists(ini, section, "AssetLocalizerSaveBackups", "AssetSDKFixerSaveBackups", GlobalVars.UserConfiguration.AssetSDKFixerSaveBackups.ToString(), write); - FileFormat.Config DefaultConfiguration = new FileFormat.Config(); - DefaultConfiguration.SelectedClient = GlobalVars.ProgramInformation.DefaultClient; - DefaultConfiguration.Map = GlobalVars.ProgramInformation.DefaultMap; - DefaultConfiguration.MapPath = GlobalPaths.MapsDir + @"\\" + GlobalVars.ProgramInformation.DefaultMap; - DefaultConfiguration.MapPathSnip = GlobalPaths.MapsDirBase + @"\\" + GlobalVars.ProgramInformation.DefaultMap; - - GlobalVars.UserConfiguration.CloseOnLaunch = ValueBool(closeonlaunch, DefaultConfiguration.CloseOnLaunch); - - if (userid.Equals("0")) + if (forcewrite) { - NovetusFuncs.GeneratePlayerID(); - Config(cfgpath, true); - } - else - { - GlobalVars.UserConfiguration.UserID = ValueInt(userid, DefaultConfiguration.UserID); - } - - GlobalVars.UserConfiguration.PlayerName = name; - GlobalVars.UserConfiguration.SelectedClient = selectedclient; - GlobalVars.UserConfiguration.Map = map; - GlobalVars.UserConfiguration.RobloxPort = ValueInt(port, DefaultConfiguration.RobloxPort); - GlobalVars.UserConfiguration.PlayerLimit = ValueInt(limit, DefaultConfiguration.PlayerLimit); - GlobalVars.UserConfiguration.UPnP = ValueBool(upnp, DefaultConfiguration.UPnP); - GlobalVars.UserConfiguration.DisabledAssetSDKHelp = ValueBool(disablehelpmessage, DefaultConfiguration.DisabledAssetSDKHelp); - GlobalVars.UserConfiguration.DiscordPresence = ValueBool(discord, DefaultConfiguration.DiscordPresence); - GlobalVars.UserConfiguration.MapPathSnip = mapsnip; - GlobalVars.UserConfiguration.GraphicsMode = (Settings.Mode)ValueInt(graphics, Convert.ToInt32(DefaultConfiguration.GraphicsMode)); - GlobalVars.UserConfiguration.ReShade = ValueBool(reshade, DefaultConfiguration.ReShade); - GlobalVars.UserConfiguration.QualityLevel = (Settings.Level)ValueInt(qualitylevel, Convert.ToInt32(DefaultConfiguration.QualityLevel)); - GlobalVars.UserConfiguration.LauncherStyle = (Settings.Style)ValueInt(style, Convert.ToInt32(DefaultConfiguration.LauncherStyle)); - GlobalVars.UserConfiguration.AssetSDKFixerSaveBackups = ValueBool(savebackups, DefaultConfiguration.AssetSDKFixerSaveBackups); - GlobalVars.UserConfiguration.AlternateServerIP = altIP; - GlobalVars.UserConfiguration.DisableReshadeDelete = ValueBool(disReshadeDel, DefaultConfiguration.DisableReshadeDelete); - GlobalVars.UserConfiguration.ShowServerNotifications = ValueBool(showNotifs, DefaultConfiguration.ShowServerNotifications); - GlobalVars.UserConfiguration.ServerBrowserServerName = SB_Name; - GlobalVars.UserConfiguration.ServerBrowserServerAddress = SB_Address; - GlobalVars.UserConfiguration.Priority = (ProcessPriorityClass)ValueInt(priority, Convert.ToInt32(DefaultConfiguration.Priority)); - GlobalVars.UserConfiguration.FirstServerLaunch = ValueBool(firstServerLaunch, DefaultConfiguration.FirstServerLaunch); - GlobalVars.UserConfiguration.NewGUI = ValueBool(newgui, DefaultConfiguration.NewGUI); - GlobalVars.UserConfiguration.URIQuickConfigure = ValueBool(quickconfigure, DefaultConfiguration.URIQuickConfigure); - GlobalVars.UserConfiguration.BootstrapperShowUI = ValueBool(bootstrapper, DefaultConfiguration.BootstrapperShowUI); - GlobalVars.UserConfiguration.WebProxyInitialSetupRequired = ValueBool(webproxysetup, DefaultConfiguration.WebProxyInitialSetupRequired); - GlobalVars.UserConfiguration.WebProxyEnabled = ValueBool(webproxy, DefaultConfiguration.WebProxyEnabled); - - string oldMapath = Path.GetDirectoryName(GlobalVars.UserConfiguration.MapPath); - //update the map path if the file doesn't exist and write to config. - if (oldMapath.Equals(GlobalPaths.MapsDir.Replace(@"\\", @"\")) && File.Exists(mappath)) - { - GlobalVars.UserConfiguration.MapPath = mappath; - } - else - { - GlobalVars.UserConfiguration.MapPath = GlobalPaths.BasePath + @"\\" + GlobalVars.UserConfiguration.MapPathSnip; - Config(cfgpath, true); - } - - if (ResetMapIfNecessary()) - { - Config(cfgpath, true); - } - } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif - Config(cfgpath, true); - } - } - - if (!forcewrite) - { - string curval = NovetusFuncs.GenerateAndReturnTripcode(); - if (!GlobalVars.PlayerTripcode.Equals(curval)) - { - GlobalVars.PlayerTripcode = curval; - } - -#if !BASICLAUNCHER - if (!File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ConfigNameCustomization)) - { - Customization(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ConfigNameCustomization, true); - } - else - { - Customization(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ConfigNameCustomization, write); - } - - ReShade(GlobalPaths.ConfigDir, "ReShade.ini", write); -#endif - } - } - - public static bool ResetMapIfNecessary() - { - if (!File.Exists(GlobalVars.UserConfiguration.MapPath)) - { - GlobalVars.UserConfiguration.Map = GlobalVars.ProgramInformation.DefaultMap; - GlobalVars.UserConfiguration.MapPath = GlobalPaths.MapsDir + @"\\" + GlobalVars.ProgramInformation.DefaultMap; - GlobalVars.UserConfiguration.MapPathSnip = GlobalPaths.MapsDirBase + @"\\" + GlobalVars.ProgramInformation.DefaultMap; - return true; - } - - return false; - } - - public static void Customization(string cfgpath, bool write) - { - if (write) - { - //WRITE - INIFile ini = new INIFile(cfgpath); - - string section = "Items"; - - ini.IniWriteValue(section, "Hat1", GlobalVars.UserCustomization.Hat1.ToString()); - ini.IniWriteValue(section, "Hat2", GlobalVars.UserCustomization.Hat2.ToString()); - ini.IniWriteValue(section, "Hat3", GlobalVars.UserCustomization.Hat3.ToString()); - ini.IniWriteValue(section, "Face", GlobalVars.UserCustomization.Face.ToString()); - ini.IniWriteValue(section, "Head", GlobalVars.UserCustomization.Head.ToString()); - ini.IniWriteValue(section, "TShirt", GlobalVars.UserCustomization.TShirt.ToString()); - ini.IniWriteValue(section, "Shirt", GlobalVars.UserCustomization.Shirt.ToString()); - ini.IniWriteValue(section, "Pants", GlobalVars.UserCustomization.Pants.ToString()); - ini.IniWriteValue(section, "Icon", GlobalVars.UserCustomization.Icon.ToString()); - ini.IniWriteValue(section, "Extra", GlobalVars.UserCustomization.Extra.ToString()); - - string section2 = "Colors"; - - ini.IniWriteValue(section2, "HeadColorID", GlobalVars.UserCustomization.HeadColorID.ToString()); - ini.IniWriteValue(section2, "HeadColorString", GlobalVars.UserCustomization.HeadColorString.ToString()); - ini.IniWriteValue(section2, "TorsoColorID", GlobalVars.UserCustomization.TorsoColorID.ToString()); - ini.IniWriteValue(section2, "TorsoColorString", GlobalVars.UserCustomization.TorsoColorString.ToString()); - ini.IniWriteValue(section2, "LeftArmColorID", GlobalVars.UserCustomization.LeftArmColorID.ToString()); - ini.IniWriteValue(section2, "LeftArmColorString", GlobalVars.UserCustomization.LeftArmColorString.ToString()); - ini.IniWriteValue(section2, "RightArmColorID", GlobalVars.UserCustomization.RightArmColorID.ToString()); - ini.IniWriteValue(section2, "RightArmColorString", GlobalVars.UserCustomization.RightArmColorString.ToString()); - ini.IniWriteValue(section2, "LeftLegColorID", GlobalVars.UserCustomization.LeftLegColorID.ToString()); - ini.IniWriteValue(section2, "LeftLegColorString", GlobalVars.UserCustomization.LeftLegColorString.ToString()); - ini.IniWriteValue(section2, "RightLegColorID", GlobalVars.UserCustomization.RightLegColorID.ToString()); - ini.IniWriteValue(section2, "RightLegColorString", GlobalVars.UserCustomization.RightLegColorString.ToString()); - - string section3 = "Other"; - - ini.IniWriteValue(section3, "CharacterID", GlobalVars.UserCustomization.CharacterID.ToString()); - ini.IniWriteValue(section3, "ExtraSelectionIsHat", GlobalVars.UserCustomization.ExtraSelectionIsHat.ToString()); - ini.IniWriteValue(section3, "ShowHatsOnExtra", GlobalVars.UserCustomization.ShowHatsInExtra.ToString()); - } - else - { - //READ - - try - { - string hat1, hat2, hat3, face, - head, tshirt, shirt, pants, icon, - extra, headcolorid, headcolorstring, torsocolorid, torsocolorstring, - larmid, larmstring, rarmid, rarmstring, llegid, - llegstring, rlegid, rlegstring, characterid, extraishat, showhatsonextra; - - INIFile ini = new INIFile(cfgpath); - - string section = "Items"; - - hat1 = ini.IniReadValue(section, "Hat1", GlobalVars.UserCustomization.Hat1.ToString()); - hat2 = ini.IniReadValue(section, "Hat2", GlobalVars.UserCustomization.Hat2.ToString()); - hat3 = ini.IniReadValue(section, "Hat3", GlobalVars.UserCustomization.Hat3.ToString()); - face = ini.IniReadValue(section, "Face", GlobalVars.UserCustomization.Face.ToString()); - head = ini.IniReadValue(section, "Head", GlobalVars.UserCustomization.Head.ToString()); - tshirt = ini.IniReadValue(section, "TShirt", GlobalVars.UserCustomization.TShirt.ToString()); - shirt = ini.IniReadValue(section, "Shirt", GlobalVars.UserCustomization.Shirt.ToString()); - pants = ini.IniReadValue(section, "Pants", GlobalVars.UserCustomization.Pants.ToString()); - icon = ini.IniReadValue(section, "Icon", GlobalVars.UserCustomization.Icon.ToString()); - extra = ini.IniReadValue(section, "Extra", GlobalVars.UserCustomization.Extra.ToString()); - - string section2 = "Colors"; - - headcolorid = ini.IniReadValue(section2, "HeadColorID", GlobalVars.UserCustomization.HeadColorID.ToString()); - headcolorstring = ini.IniReadValue(section2, "HeadColorString", GlobalVars.UserCustomization.HeadColorString.ToString()); - torsocolorid = ini.IniReadValue(section2, "TorsoColorID", GlobalVars.UserCustomization.TorsoColorID.ToString()); - torsocolorstring = ini.IniReadValue(section2, "TorsoColorString", GlobalVars.UserCustomization.TorsoColorString.ToString()); - larmid = ini.IniReadValue(section2, "LeftArmColorID", GlobalVars.UserCustomization.LeftArmColorID.ToString()); - larmstring = ini.IniReadValue(section2, "LeftArmColorString", GlobalVars.UserCustomization.LeftArmColorString.ToString()); - rarmid = ini.IniReadValue(section2, "RightArmColorID", GlobalVars.UserCustomization.RightArmColorID.ToString()); - rarmstring = ini.IniReadValue(section2, "RightArmColorString", GlobalVars.UserCustomization.RightArmColorString.ToString()); - llegid = ini.IniReadValue(section2, "LeftLegColorID", GlobalVars.UserCustomization.LeftLegColorID.ToString()); - llegstring = ini.IniReadValue(section2, "LeftLegColorString", GlobalVars.UserCustomization.LeftLegColorString.ToString()); - rlegid = ini.IniReadValue(section2, "RightLegColorID", GlobalVars.UserCustomization.RightLegColorID.ToString()); - rlegstring = ini.IniReadValue(section2, "RightLegColorString", GlobalVars.UserCustomization.RightLegColorString.ToString()); - - string section3 = "Other"; - - characterid = ini.IniReadValue(section3, "CharacterID", GlobalVars.UserCustomization.CharacterID.ToString()); - extraishat = ini.IniReadValue(section3, "ExtraSelectionIsHat", GlobalVars.UserCustomization.ExtraSelectionIsHat.ToString()); - showhatsonextra = ini.IniReadValue(section3, "ShowHatsOnExtra", GlobalVars.UserCustomization.ShowHatsInExtra.ToString()); - - FileFormat.CustomizationConfig DefaultCustomization = new FileFormat.CustomizationConfig(); - - GlobalVars.UserCustomization.Hat1 = hat1; - GlobalVars.UserCustomization.Hat2 = hat2; - GlobalVars.UserCustomization.Hat3 = hat3; - - GlobalVars.UserCustomization.HeadColorID = ValueInt(headcolorid, DefaultCustomization.HeadColorID); - GlobalVars.UserCustomization.TorsoColorID = ValueInt(torsocolorid, DefaultCustomization.TorsoColorID); - GlobalVars.UserCustomization.LeftArmColorID = ValueInt(larmid, DefaultCustomization.LeftArmColorID); - GlobalVars.UserCustomization.RightArmColorID = ValueInt(rarmid, DefaultCustomization.RightArmColorID); - GlobalVars.UserCustomization.LeftLegColorID = ValueInt(llegid, DefaultCustomization.LeftLegColorID); - GlobalVars.UserCustomization.RightLegColorID = ValueInt(rlegid, DefaultCustomization.RightArmColorID); - - GlobalVars.UserCustomization.HeadColorString = headcolorstring; - GlobalVars.UserCustomization.TorsoColorString = torsocolorstring; - GlobalVars.UserCustomization.LeftArmColorString = larmstring; - GlobalVars.UserCustomization.RightArmColorString = rarmstring; - GlobalVars.UserCustomization.LeftLegColorString = llegstring; - GlobalVars.UserCustomization.RightLegColorString = rlegstring; - - GlobalVars.UserCustomization.Face = face; - GlobalVars.UserCustomization.Head = head; - GlobalVars.UserCustomization.TShirt = tshirt; - GlobalVars.UserCustomization.Shirt = shirt; - GlobalVars.UserCustomization.Pants = pants; - GlobalVars.UserCustomization.Icon = icon; - - GlobalVars.UserCustomization.CharacterID = characterid; - GlobalVars.UserCustomization.Extra = extra; - GlobalVars.UserCustomization.ExtraSelectionIsHat = ValueBool(extraishat, DefaultCustomization.ExtraSelectionIsHat); - GlobalVars.UserCustomization.ShowHatsInExtra = ValueBool(showhatsonextra, DefaultCustomization.ShowHatsInExtra); - } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif - Customization(cfgpath, true); - } - } - - ReloadLoadoutValue(); - } - - public static void ReShade(string cfgpath, string cfgname, bool write) - { - string fullpath = cfgpath + "\\" + cfgname; - - if (!File.Exists(fullpath)) - { - Util.FixedFileCopy(GlobalPaths.ConfigDir + "\\ReShade_default.ini", fullpath, false); - ReShadeValues(fullpath, write, true); - } - else - { - ReShadeValues(fullpath, write, true); - } - - string clientdir = GlobalPaths.ClientDir; - DirectoryInfo dinfo = new DirectoryInfo(clientdir); - DirectoryInfo[] Dirs = dinfo.GetDirectories(); - foreach (DirectoryInfo dir in Dirs) - { - string fulldirpath = dir.FullName + @"\" + cfgname; - string dllfilename = "opengl32.dll"; - string fulldllpath = dir.FullName + @"\" + dllfilename; - - if (GlobalVars.UserConfiguration.ReShade) - { - if (!File.Exists(fulldirpath)) - { - Util.FixedFileCopy(fullpath, fulldirpath, false); - ReShadeValues(fulldirpath, write, false); - } - else - { - ReShadeValues(fulldirpath, write, false); - } - - if (!File.Exists(fulldllpath)) - { - Util.FixedFileCopy(GlobalPaths.DataDir + "\\" + dllfilename, fulldllpath, false); + // try again.... + Config(cfgpath, false, doubleCheck); } } else - { - Util.FixedFileDelete(fulldirpath); - - if (!GlobalVars.UserConfiguration.DisableReshadeDelete) - { - Util.FixedFileDelete(fulldllpath); - } - } - } - } - - public static void ReShadeValues(string cfgpath, bool write, bool setglobals) - { - if (write) - { - //WRITE - INIFile ini = new INIFile(cfgpath); - - string section = "GENERAL"; - string section2 = "OVERLAY"; - - int FPS = GlobalVars.UserConfiguration.ReShadeFPSDisplay ? 1 : 0; - ini.IniWriteValue(section2, "ShowFPS", FPS.ToString()); - ini.IniWriteValue(section2, "ShowFrameTime", FPS.ToString()); - int PerformanceMode = GlobalVars.UserConfiguration.ReShadePerformanceMode ? 1 : 0; - ini.IniWriteValue(section, "PerformanceMode", PerformanceMode.ToString()); - } - else - { - //READ - string framerate, frametime, performance; - - INIFile ini = new INIFile(cfgpath); - - string section = "GENERAL"; - string section2 = "OVERLAY"; - - int FPS = GlobalVars.UserConfiguration.ReShadeFPSDisplay ? 1 : 0; - framerate = ini.IniReadValue(section2, "ShowFPS", FPS.ToString()); - frametime = ini.IniReadValue(section2, "ShowFrameTime", FPS.ToString()); - int PerformanceMode = GlobalVars.UserConfiguration.ReShadePerformanceMode ? 1 : 0; - performance = ini.IniReadValue(section, "PerformanceMode", PerformanceMode.ToString()); - - if (setglobals) { try { - switch (ValueInt(framerate, 0)) + //READ + string closeonlaunch, userid, name, selectedclient, + map, port, limit, upnp, + disablehelpmessage, discord, mappath, mapsnip, + graphics, reshade, qualitylevel, style, savebackups, altIP, + disReshadeDel, showNotifs, SB_Name, SB_Address, priority, + firstServerLaunch, newgui, quickconfigure, bootstrapper, + webproxysetup, webproxy; + + INIFile ini = new INIFile(cfgpath); + + string section = "Config"; + + closeonlaunch = ini.IniReadValue(section, "CloseOnLaunch", GlobalVars.UserConfiguration.CloseOnLaunch.ToString()); + userid = ini.IniReadValue(section, "UserID", GlobalVars.UserConfiguration.UserID.ToString()); + name = ini.IniReadValue(section, "PlayerName", GlobalVars.UserConfiguration.PlayerName.ToString()); + selectedclient = ini.IniReadValue(section, "SelectedClient", GlobalVars.UserConfiguration.SelectedClient.ToString()); + map = ini.IniReadValue(section, "Map", GlobalVars.UserConfiguration.Map.ToString()); + port = ini.IniReadValue(section, "RobloxPort", GlobalVars.UserConfiguration.RobloxPort.ToString()); + limit = ini.IniReadValue(section, "PlayerLimit", GlobalVars.UserConfiguration.PlayerLimit.ToString()); + upnp = ini.IniReadValue(section, "UPnP", GlobalVars.UserConfiguration.UPnP.ToString()); + discord = ini.IniReadValue(section, "DiscordRichPresence", GlobalVars.UserConfiguration.DiscordPresence.ToString()); + mappath = ini.IniReadValue(section, "MapPath", GlobalVars.UserConfiguration.MapPath.ToString()); + mapsnip = ini.IniReadValue(section, "MapPathSnip", GlobalVars.UserConfiguration.MapPathSnip.ToString()); + graphics = ini.IniReadValue(section, "GraphicsMode", ((int)GlobalVars.UserConfiguration.GraphicsMode).ToString()); + reshade = ini.IniReadValue(section, "ReShade", GlobalVars.UserConfiguration.ReShade.ToString()); + qualitylevel = ini.IniReadValue(section, "QualityLevel", ((int)GlobalVars.UserConfiguration.QualityLevel).ToString()); + style = ini.IniReadValue(section, "Style", ((int)GlobalVars.UserConfiguration.LauncherStyle).ToString()); + altIP = ini.IniReadValue(section, "AlternateServerIP", GlobalVars.UserConfiguration.AlternateServerIP.ToString()); + disReshadeDel = ini.IniReadValue(section, "DisableReshadeDelete", GlobalVars.UserConfiguration.DisableReshadeDelete.ToString()); + showNotifs = ini.IniReadValue(section, "ShowServerNotifications", GlobalVars.UserConfiguration.ShowServerNotifications.ToString()); + SB_Name = ini.IniReadValue(section, "ServerBrowserServerName", GlobalVars.UserConfiguration.ServerBrowserServerName.ToString()); + SB_Address = ini.IniReadValue(section, "ServerBrowserServerAddress", GlobalVars.UserConfiguration.ServerBrowserServerAddress.ToString()); + priority = ini.IniReadValue(section, "ClientLaunchPriority", ((int)GlobalVars.UserConfiguration.Priority).ToString()); + firstServerLaunch = ini.IniReadValue(section, "FirstServerLaunch", GlobalVars.UserConfiguration.FirstServerLaunch.ToString()); + newgui = ini.IniReadValue(section, "NewGUI", GlobalVars.UserConfiguration.NewGUI.ToString()); + quickconfigure = ini.IniReadValue(section, "URIQuickConfigure", GlobalVars.UserConfiguration.URIQuickConfigure.ToString()); + bootstrapper = ini.IniReadValue(section, "BootstrapperShowUI", GlobalVars.UserConfiguration.BootstrapperShowUI.ToString()); + webproxysetup = ini.IniReadValue(section, "WebProxyInitialSetupRequired", GlobalVars.UserConfiguration.WebProxyInitialSetupRequired.ToString()); + webproxy = ini.IniReadValue(section, "WebProxyEnabled", GlobalVars.UserConfiguration.WebProxyEnabled.ToString()); + disablehelpmessage = ConfigUseOldValIfExists(ini, section, "ItemMakerDisableHelpMessage", "AssetSDKDisableHelpMessage", GlobalVars.UserConfiguration.DisabledAssetSDKHelp.ToString(), write); + savebackups = ConfigUseOldValIfExists(ini, section, "AssetLocalizerSaveBackups", "AssetSDKFixerSaveBackups", GlobalVars.UserConfiguration.AssetSDKFixerSaveBackups.ToString(), write); + + FileFormat.Config DefaultConfiguration = new FileFormat.Config(); + DefaultConfiguration.SelectedClient = GlobalVars.ProgramInformation.DefaultClient; + DefaultConfiguration.Map = GlobalVars.ProgramInformation.DefaultMap; + DefaultConfiguration.MapPath = GlobalPaths.MapsDir + @"\\" + GlobalVars.ProgramInformation.DefaultMap; + DefaultConfiguration.MapPathSnip = GlobalPaths.MapsDirBase + @"\\" + GlobalVars.ProgramInformation.DefaultMap; + + GlobalVars.UserConfiguration.CloseOnLaunch = ValueBool(closeonlaunch, DefaultConfiguration.CloseOnLaunch); + + if (userid.Equals("0")) { - case int showFPSLine when showFPSLine == 1 && Convert.ToInt32(frametime) == 1: - GlobalVars.UserConfiguration.ReShadeFPSDisplay = true; - break; - default: - GlobalVars.UserConfiguration.ReShadeFPSDisplay = false; - break; + NovetusFuncs.GeneratePlayerID(); + Config(cfgpath, true); + } + else + { + GlobalVars.UserConfiguration.UserID = ValueInt(userid, DefaultConfiguration.UserID); } - switch (ValueInt(performance, 0)) + GlobalVars.UserConfiguration.PlayerName = name; + GlobalVars.UserConfiguration.SelectedClient = selectedclient; + GlobalVars.UserConfiguration.Map = map; + GlobalVars.UserConfiguration.RobloxPort = ValueInt(port, DefaultConfiguration.RobloxPort); + GlobalVars.UserConfiguration.PlayerLimit = ValueInt(limit, DefaultConfiguration.PlayerLimit); + GlobalVars.UserConfiguration.UPnP = ValueBool(upnp, DefaultConfiguration.UPnP); + GlobalVars.UserConfiguration.DisabledAssetSDKHelp = ValueBool(disablehelpmessage, DefaultConfiguration.DisabledAssetSDKHelp); + GlobalVars.UserConfiguration.DiscordPresence = ValueBool(discord, DefaultConfiguration.DiscordPresence); + GlobalVars.UserConfiguration.MapPathSnip = mapsnip; + GlobalVars.UserConfiguration.GraphicsMode = (Settings.Mode)ValueInt(graphics, Convert.ToInt32(DefaultConfiguration.GraphicsMode)); + GlobalVars.UserConfiguration.ReShade = ValueBool(reshade, DefaultConfiguration.ReShade); + GlobalVars.UserConfiguration.QualityLevel = (Settings.Level)ValueInt(qualitylevel, Convert.ToInt32(DefaultConfiguration.QualityLevel)); + GlobalVars.UserConfiguration.LauncherStyle = (Settings.Style)ValueInt(style, Convert.ToInt32(DefaultConfiguration.LauncherStyle)); + GlobalVars.UserConfiguration.AssetSDKFixerSaveBackups = ValueBool(savebackups, DefaultConfiguration.AssetSDKFixerSaveBackups); + GlobalVars.UserConfiguration.AlternateServerIP = altIP; + GlobalVars.UserConfiguration.DisableReshadeDelete = ValueBool(disReshadeDel, DefaultConfiguration.DisableReshadeDelete); + GlobalVars.UserConfiguration.ShowServerNotifications = ValueBool(showNotifs, DefaultConfiguration.ShowServerNotifications); + GlobalVars.UserConfiguration.ServerBrowserServerName = SB_Name; + GlobalVars.UserConfiguration.ServerBrowserServerAddress = SB_Address; + GlobalVars.UserConfiguration.Priority = (ProcessPriorityClass)ValueInt(priority, Convert.ToInt32(DefaultConfiguration.Priority)); + GlobalVars.UserConfiguration.FirstServerLaunch = ValueBool(firstServerLaunch, DefaultConfiguration.FirstServerLaunch); + GlobalVars.UserConfiguration.NewGUI = ValueBool(newgui, DefaultConfiguration.NewGUI); + GlobalVars.UserConfiguration.URIQuickConfigure = ValueBool(quickconfigure, DefaultConfiguration.URIQuickConfigure); + GlobalVars.UserConfiguration.BootstrapperShowUI = ValueBool(bootstrapper, DefaultConfiguration.BootstrapperShowUI); + GlobalVars.UserConfiguration.WebProxyInitialSetupRequired = ValueBool(webproxysetup, DefaultConfiguration.WebProxyInitialSetupRequired); + GlobalVars.UserConfiguration.WebProxyEnabled = ValueBool(webproxy, DefaultConfiguration.WebProxyEnabled); + + string oldMapath = Path.GetDirectoryName(GlobalVars.UserConfiguration.MapPath); + //update the map path if the file doesn't exist and write to config. + if (oldMapath.Equals(GlobalPaths.MapsDir.Replace(@"\\", @"\")) && File.Exists(mappath)) { - case 1: - GlobalVars.UserConfiguration.ReShadePerformanceMode = true; - break; - default: - GlobalVars.UserConfiguration.ReShadePerformanceMode = false; - break; + GlobalVars.UserConfiguration.MapPath = mappath; + } + else + { + GlobalVars.UserConfiguration.MapPath = GlobalPaths.BasePath + @"\\" + GlobalVars.UserConfiguration.MapPathSnip; + Config(cfgpath, true); + } + + if (ResetMapIfNecessary()) + { + Config(cfgpath, true); } } #if URI || LAUNCHER || BASICLAUNCHER @@ -1252,254 +962,547 @@ public class FileManagement { Util.LogExceptions(ex); #else - catch (Exception) - { + catch (Exception) + { #endif - ReShadeValues(cfgpath, true, setglobals); + Config(cfgpath, true); } } - } - } - public static bool InitColors() - { - try - { - if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.PartColorXMLName)) + if (!forcewrite) { - GlobalVars.PartColorList = PartColorLoader.GetPartColors(); - GlobalVars.PartColorListConv = new List(); - GlobalVars.PartColorListConv.AddRange(GlobalVars.PartColorList); + string curval = NovetusFuncs.GenerateAndReturnTripcode(); + if (!GlobalVars.PlayerTripcode.Equals(curval)) + { + GlobalVars.PlayerTripcode = curval; + } + +#if !BASICLAUNCHER + if (!File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ConfigNameCustomization)) + { + Customization(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ConfigNameCustomization, true); + } + else + { + Customization(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ConfigNameCustomization, write); + } + + ReShade(GlobalPaths.ConfigDir, "ReShade.ini", write); +#endif + } + } + + public static bool ResetMapIfNecessary() + { + if (!File.Exists(GlobalVars.UserConfiguration.MapPath)) + { + GlobalVars.UserConfiguration.Map = GlobalVars.ProgramInformation.DefaultMap; + GlobalVars.UserConfiguration.MapPath = GlobalPaths.MapsDir + @"\\" + GlobalVars.ProgramInformation.DefaultMap; + GlobalVars.UserConfiguration.MapPathSnip = GlobalPaths.MapsDirBase + @"\\" + GlobalVars.ProgramInformation.DefaultMap; return true; } + + return false; + } + + public static void Customization(string cfgpath, bool write) + { + if (write) + { + //WRITE + INIFile ini = new INIFile(cfgpath); + + string section = "Items"; + + ini.IniWriteValue(section, "Hat1", GlobalVars.UserCustomization.Hat1.ToString()); + ini.IniWriteValue(section, "Hat2", GlobalVars.UserCustomization.Hat2.ToString()); + ini.IniWriteValue(section, "Hat3", GlobalVars.UserCustomization.Hat3.ToString()); + ini.IniWriteValue(section, "Face", GlobalVars.UserCustomization.Face.ToString()); + ini.IniWriteValue(section, "Head", GlobalVars.UserCustomization.Head.ToString()); + ini.IniWriteValue(section, "TShirt", GlobalVars.UserCustomization.TShirt.ToString()); + ini.IniWriteValue(section, "Shirt", GlobalVars.UserCustomization.Shirt.ToString()); + ini.IniWriteValue(section, "Pants", GlobalVars.UserCustomization.Pants.ToString()); + ini.IniWriteValue(section, "Icon", GlobalVars.UserCustomization.Icon.ToString()); + ini.IniWriteValue(section, "Extra", GlobalVars.UserCustomization.Extra.ToString()); + + string section2 = "Colors"; + + ini.IniWriteValue(section2, "HeadColorID", GlobalVars.UserCustomization.HeadColorID.ToString()); + ini.IniWriteValue(section2, "HeadColorString", GlobalVars.UserCustomization.HeadColorString.ToString()); + ini.IniWriteValue(section2, "TorsoColorID", GlobalVars.UserCustomization.TorsoColorID.ToString()); + ini.IniWriteValue(section2, "TorsoColorString", GlobalVars.UserCustomization.TorsoColorString.ToString()); + ini.IniWriteValue(section2, "LeftArmColorID", GlobalVars.UserCustomization.LeftArmColorID.ToString()); + ini.IniWriteValue(section2, "LeftArmColorString", GlobalVars.UserCustomization.LeftArmColorString.ToString()); + ini.IniWriteValue(section2, "RightArmColorID", GlobalVars.UserCustomization.RightArmColorID.ToString()); + ini.IniWriteValue(section2, "RightArmColorString", GlobalVars.UserCustomization.RightArmColorString.ToString()); + ini.IniWriteValue(section2, "LeftLegColorID", GlobalVars.UserCustomization.LeftLegColorID.ToString()); + ini.IniWriteValue(section2, "LeftLegColorString", GlobalVars.UserCustomization.LeftLegColorString.ToString()); + ini.IniWriteValue(section2, "RightLegColorID", GlobalVars.UserCustomization.RightLegColorID.ToString()); + ini.IniWriteValue(section2, "RightLegColorString", GlobalVars.UserCustomization.RightLegColorString.ToString()); + + string section3 = "Other"; + + ini.IniWriteValue(section3, "CharacterID", GlobalVars.UserCustomization.CharacterID.ToString()); + ini.IniWriteValue(section3, "ExtraSelectionIsHat", GlobalVars.UserCustomization.ExtraSelectionIsHat.ToString()); + ini.IniWriteValue(section3, "ShowHatsOnExtra", GlobalVars.UserCustomization.ShowHatsInExtra.ToString()); + } else { - goto Failure; + //READ + + try + { + string hat1, hat2, hat3, face, + head, tshirt, shirt, pants, icon, + extra, headcolorid, headcolorstring, torsocolorid, torsocolorstring, + larmid, larmstring, rarmid, rarmstring, llegid, + llegstring, rlegid, rlegstring, characterid, extraishat, showhatsonextra; + + INIFile ini = new INIFile(cfgpath); + + string section = "Items"; + + hat1 = ini.IniReadValue(section, "Hat1", GlobalVars.UserCustomization.Hat1.ToString()); + hat2 = ini.IniReadValue(section, "Hat2", GlobalVars.UserCustomization.Hat2.ToString()); + hat3 = ini.IniReadValue(section, "Hat3", GlobalVars.UserCustomization.Hat3.ToString()); + face = ini.IniReadValue(section, "Face", GlobalVars.UserCustomization.Face.ToString()); + head = ini.IniReadValue(section, "Head", GlobalVars.UserCustomization.Head.ToString()); + tshirt = ini.IniReadValue(section, "TShirt", GlobalVars.UserCustomization.TShirt.ToString()); + shirt = ini.IniReadValue(section, "Shirt", GlobalVars.UserCustomization.Shirt.ToString()); + pants = ini.IniReadValue(section, "Pants", GlobalVars.UserCustomization.Pants.ToString()); + icon = ini.IniReadValue(section, "Icon", GlobalVars.UserCustomization.Icon.ToString()); + extra = ini.IniReadValue(section, "Extra", GlobalVars.UserCustomization.Extra.ToString()); + + string section2 = "Colors"; + + headcolorid = ini.IniReadValue(section2, "HeadColorID", GlobalVars.UserCustomization.HeadColorID.ToString()); + headcolorstring = ini.IniReadValue(section2, "HeadColorString", GlobalVars.UserCustomization.HeadColorString.ToString()); + torsocolorid = ini.IniReadValue(section2, "TorsoColorID", GlobalVars.UserCustomization.TorsoColorID.ToString()); + torsocolorstring = ini.IniReadValue(section2, "TorsoColorString", GlobalVars.UserCustomization.TorsoColorString.ToString()); + larmid = ini.IniReadValue(section2, "LeftArmColorID", GlobalVars.UserCustomization.LeftArmColorID.ToString()); + larmstring = ini.IniReadValue(section2, "LeftArmColorString", GlobalVars.UserCustomization.LeftArmColorString.ToString()); + rarmid = ini.IniReadValue(section2, "RightArmColorID", GlobalVars.UserCustomization.RightArmColorID.ToString()); + rarmstring = ini.IniReadValue(section2, "RightArmColorString", GlobalVars.UserCustomization.RightArmColorString.ToString()); + llegid = ini.IniReadValue(section2, "LeftLegColorID", GlobalVars.UserCustomization.LeftLegColorID.ToString()); + llegstring = ini.IniReadValue(section2, "LeftLegColorString", GlobalVars.UserCustomization.LeftLegColorString.ToString()); + rlegid = ini.IniReadValue(section2, "RightLegColorID", GlobalVars.UserCustomization.RightLegColorID.ToString()); + rlegstring = ini.IniReadValue(section2, "RightLegColorString", GlobalVars.UserCustomization.RightLegColorString.ToString()); + + string section3 = "Other"; + + characterid = ini.IniReadValue(section3, "CharacterID", GlobalVars.UserCustomization.CharacterID.ToString()); + extraishat = ini.IniReadValue(section3, "ExtraSelectionIsHat", GlobalVars.UserCustomization.ExtraSelectionIsHat.ToString()); + showhatsonextra = ini.IniReadValue(section3, "ShowHatsOnExtra", GlobalVars.UserCustomization.ShowHatsInExtra.ToString()); + + FileFormat.CustomizationConfig DefaultCustomization = new FileFormat.CustomizationConfig(); + + GlobalVars.UserCustomization.Hat1 = hat1; + GlobalVars.UserCustomization.Hat2 = hat2; + GlobalVars.UserCustomization.Hat3 = hat3; + + GlobalVars.UserCustomization.HeadColorID = ValueInt(headcolorid, DefaultCustomization.HeadColorID); + GlobalVars.UserCustomization.TorsoColorID = ValueInt(torsocolorid, DefaultCustomization.TorsoColorID); + GlobalVars.UserCustomization.LeftArmColorID = ValueInt(larmid, DefaultCustomization.LeftArmColorID); + GlobalVars.UserCustomization.RightArmColorID = ValueInt(rarmid, DefaultCustomization.RightArmColorID); + GlobalVars.UserCustomization.LeftLegColorID = ValueInt(llegid, DefaultCustomization.LeftLegColorID); + GlobalVars.UserCustomization.RightLegColorID = ValueInt(rlegid, DefaultCustomization.RightArmColorID); + + GlobalVars.UserCustomization.HeadColorString = headcolorstring; + GlobalVars.UserCustomization.TorsoColorString = torsocolorstring; + GlobalVars.UserCustomization.LeftArmColorString = larmstring; + GlobalVars.UserCustomization.RightArmColorString = rarmstring; + GlobalVars.UserCustomization.LeftLegColorString = llegstring; + GlobalVars.UserCustomization.RightLegColorString = rlegstring; + + GlobalVars.UserCustomization.Face = face; + GlobalVars.UserCustomization.Head = head; + GlobalVars.UserCustomization.TShirt = tshirt; + GlobalVars.UserCustomization.Shirt = shirt; + GlobalVars.UserCustomization.Pants = pants; + GlobalVars.UserCustomization.Icon = icon; + + GlobalVars.UserCustomization.CharacterID = characterid; + GlobalVars.UserCustomization.Extra = extra; + GlobalVars.UserCustomization.ExtraSelectionIsHat = ValueBool(extraishat, DefaultCustomization.ExtraSelectionIsHat); + GlobalVars.UserCustomization.ShowHatsInExtra = ValueBool(showhatsonextra, DefaultCustomization.ShowHatsInExtra); + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); +#else + catch (Exception) + { +#endif + Customization(cfgpath, true); + } + } + + ReloadLoadoutValue(); + } + + public static void ReShade(string cfgpath, string cfgname, bool write) + { + string fullpath = cfgpath + "\\" + cfgname; + + if (!File.Exists(fullpath)) + { + Util.FixedFileCopy(GlobalPaths.ConfigDir + "\\ReShade_default.ini", fullpath, false); + ReShadeValues(fullpath, write, true); + } + else + { + ReShadeValues(fullpath, write, true); + } + + string clientdir = GlobalPaths.ClientDir; + DirectoryInfo dinfo = new DirectoryInfo(clientdir); + DirectoryInfo[] Dirs = dinfo.GetDirectories(); + foreach (DirectoryInfo dir in Dirs) + { + string fulldirpath = dir.FullName + @"\" + cfgname; + string dllfilename = "opengl32.dll"; + string fulldllpath = dir.FullName + @"\" + dllfilename; + + if (GlobalVars.UserConfiguration.ReShade) + { + if (!File.Exists(fulldirpath)) + { + Util.FixedFileCopy(fullpath, fulldirpath, false); + ReShadeValues(fulldirpath, write, false); + } + else + { + ReShadeValues(fulldirpath, write, false); + } + + if (!File.Exists(fulldllpath)) + { + Util.FixedFileCopy(GlobalPaths.DataDir + "\\" + dllfilename, fulldllpath, false); + } + } + else + { + Util.FixedFileDelete(fulldirpath); + + if (!GlobalVars.UserConfiguration.DisableReshadeDelete) + { + Util.FixedFileDelete(fulldllpath); + } + } } } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) + + public static void ReShadeValues(string cfgpath, bool write, bool setglobals) { - Util.LogExceptions(ex); + if (write) + { + //WRITE + INIFile ini = new INIFile(cfgpath); + + string section = "GENERAL"; + string section2 = "OVERLAY"; + + int FPS = GlobalVars.UserConfiguration.ReShadeFPSDisplay ? 1 : 0; + ini.IniWriteValue(section2, "ShowFPS", FPS.ToString()); + ini.IniWriteValue(section2, "ShowFrameTime", FPS.ToString()); + int PerformanceMode = GlobalVars.UserConfiguration.ReShadePerformanceMode ? 1 : 0; + ini.IniWriteValue(section, "PerformanceMode", PerformanceMode.ToString()); + } + else + { + //READ + string framerate, frametime, performance; + + INIFile ini = new INIFile(cfgpath); + + string section = "GENERAL"; + string section2 = "OVERLAY"; + + int FPS = GlobalVars.UserConfiguration.ReShadeFPSDisplay ? 1 : 0; + framerate = ini.IniReadValue(section2, "ShowFPS", FPS.ToString()); + frametime = ini.IniReadValue(section2, "ShowFrameTime", FPS.ToString()); + int PerformanceMode = GlobalVars.UserConfiguration.ReShadePerformanceMode ? 1 : 0; + performance = ini.IniReadValue(section, "PerformanceMode", PerformanceMode.ToString()); + + if (setglobals) + { + try + { + switch (ValueInt(framerate, 0)) + { + case int showFPSLine when showFPSLine == 1 && Convert.ToInt32(frametime) == 1: + GlobalVars.UserConfiguration.ReShadeFPSDisplay = true; + break; + default: + GlobalVars.UserConfiguration.ReShadeFPSDisplay = false; + break; + } + + switch (ValueInt(performance, 0)) + { + case 1: + GlobalVars.UserConfiguration.ReShadePerformanceMode = true; + break; + default: + GlobalVars.UserConfiguration.ReShadePerformanceMode = false; + break; + } + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); #else - catch (Exception) - { + catch (Exception) + { #endif - goto Failure; + ReShadeValues(cfgpath, true, setglobals); + } + } + } } - Failure: - return false; - } - - public static bool HasColorsChanged() - { - try + public static bool InitColors() { - PartColor[] tempList; - - if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.PartColorXMLName)) + try { - tempList = PartColorLoader.GetPartColors(); - if (tempList.Length != GlobalVars.PartColorList.Length) + if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.PartColorXMLName)) { + GlobalVars.PartColorList = PartColorLoader.GetPartColors(); + GlobalVars.PartColorListConv = new List(); + GlobalVars.PartColorListConv.AddRange(GlobalVars.PartColorList); return true; } else { - return false; + goto Failure; } } - else - { - goto Failure; - } - } #if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); + catch (Exception ex) + { + Util.LogExceptions(ex); #else catch (Exception) { #endif - goto Failure; + goto Failure; + } + + Failure: + return false; } - Failure: - return false; - } + public static bool HasColorsChanged() + { + try + { + PartColor[] tempList; + + if (File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.PartColorXMLName)) + { + tempList = PartColorLoader.GetPartColors(); + if (tempList.Length != GlobalVars.PartColorList.Length) + { + return true; + } + else + { + return false; + } + } + else + { + goto Failure; + } + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); +#else + catch (Exception) + { +#endif + goto Failure; + } + + Failure: + return false; + } #if LAUNCHER public static void ResetConfigValues(Settings.Style style) #else - public static void ResetConfigValues() + public static void ResetConfigValues() #endif - { - bool WebProxySetupComplete = GlobalVars.UserConfiguration.WebProxyInitialSetupRequired; - bool WebProxy = GlobalVars.UserConfiguration.WebProxyEnabled; + { + bool WebProxySetupComplete = GlobalVars.UserConfiguration.WebProxyInitialSetupRequired; + bool WebProxy = GlobalVars.UserConfiguration.WebProxyEnabled; - GlobalVars.UserConfiguration = new FileFormat.Config(); - GlobalVars.UserConfiguration.SelectedClient = GlobalVars.ProgramInformation.DefaultClient; - GlobalVars.UserConfiguration.Map = GlobalVars.ProgramInformation.DefaultMap; - GlobalVars.UserConfiguration.MapPath = GlobalPaths.MapsDir + @"\\" + GlobalVars.ProgramInformation.DefaultMap; - GlobalVars.UserConfiguration.MapPathSnip = GlobalPaths.MapsDirBase + @"\\" + GlobalVars.ProgramInformation.DefaultMap; + GlobalVars.UserConfiguration = new FileFormat.Config(); + GlobalVars.UserConfiguration.SelectedClient = GlobalVars.ProgramInformation.DefaultClient; + GlobalVars.UserConfiguration.Map = GlobalVars.ProgramInformation.DefaultMap; + GlobalVars.UserConfiguration.MapPath = GlobalPaths.MapsDir + @"\\" + GlobalVars.ProgramInformation.DefaultMap; + GlobalVars.UserConfiguration.MapPathSnip = GlobalPaths.MapsDirBase + @"\\" + GlobalVars.ProgramInformation.DefaultMap; #if LAUNCHER GlobalVars.UserConfiguration.LauncherStyle = style; #endif - GlobalVars.UserConfiguration.WebProxyInitialSetupRequired = WebProxySetupComplete; - GlobalVars.UserConfiguration.WebProxyEnabled = WebProxy; - NovetusFuncs.GeneratePlayerID(); - ResetCustomizationValues(); - } - - public static void ResetCustomizationValues() - { - GlobalVars.UserCustomization = new FileFormat.CustomizationConfig(); - ReloadLoadoutValue(); - } - - public static void ReloadLoadoutValue(bool localizeOnlineClothing = false) - { - string hat1 = (!GlobalVars.UserCustomization.Hat1.EndsWith("-Solo.rbxm")) ? GlobalVars.UserCustomization.Hat1 : "NoHat.rbxm"; - string hat2 = (!GlobalVars.UserCustomization.Hat2.EndsWith("-Solo.rbxm")) ? GlobalVars.UserCustomization.Hat2 : "NoHat.rbxm"; - string hat3 = (!GlobalVars.UserCustomization.Hat3.EndsWith("-Solo.rbxm")) ? GlobalVars.UserCustomization.Hat3 : "NoHat.rbxm"; - string extra = (!GlobalVars.UserCustomization.Extra.EndsWith("-Solo.rbxm")) ? GlobalVars.UserCustomization.Extra : "NoExtra.rbxm"; - - GlobalVars.Loadout = "'" + hat1 + "','" + - hat2 + "','" + - hat3 + "'," + - GlobalVars.UserCustomization.HeadColorID + "," + - GlobalVars.UserCustomization.TorsoColorID + "," + - GlobalVars.UserCustomization.LeftArmColorID + "," + - GlobalVars.UserCustomization.RightArmColorID + "," + - GlobalVars.UserCustomization.LeftLegColorID + "," + - GlobalVars.UserCustomization.RightLegColorID + ",'" + - GlobalVars.UserCustomization.TShirt + "','" + - GlobalVars.UserCustomization.Shirt + "','" + - GlobalVars.UserCustomization.Pants + "','" + - GlobalVars.UserCustomization.Face + "','" + - GlobalVars.UserCustomization.Head + "','" + - GlobalVars.UserCustomization.Icon + "','" + - extra + "'"; - - GlobalVars.soloLoadout = "'" + GlobalVars.UserCustomization.Hat1 + "','" + - GlobalVars.UserCustomization.Hat2 + "','" + - GlobalVars.UserCustomization.Hat3 + "'," + - GlobalVars.UserCustomization.HeadColorID + "," + - GlobalVars.UserCustomization.TorsoColorID + "," + - GlobalVars.UserCustomization.LeftArmColorID + "," + - GlobalVars.UserCustomization.RightArmColorID + "," + - GlobalVars.UserCustomization.LeftLegColorID + "," + - GlobalVars.UserCustomization.RightLegColorID + ",'" + - GlobalVars.UserCustomization.TShirt + "','" + - GlobalVars.UserCustomization.Shirt + "','" + - GlobalVars.UserCustomization.Pants + "','" + - GlobalVars.UserCustomization.Face + "','" + - GlobalVars.UserCustomization.Head + "','" + - GlobalVars.UserCustomization.Icon + "','" + - GlobalVars.UserCustomization.Extra + "'"; - - if (localizeOnlineClothing) - { - GlobalVars.TShirtTextureID = NovetusFuncs.GetItemTextureID(GlobalVars.UserCustomization.TShirt, "TShirt", new AssetCacheDefBasic("ShirtGraphic", new string[] { "Graphic" })); - GlobalVars.ShirtTextureID = NovetusFuncs.GetItemTextureID(GlobalVars.UserCustomization.Shirt, "Shirt", new AssetCacheDefBasic("Shirt", new string[] { "ShirtTemplate" })); - GlobalVars.PantsTextureID = NovetusFuncs.GetItemTextureID(GlobalVars.UserCustomization.Pants, "Pants", new AssetCacheDefBasic("Pants", new string[] { "PantsTemplate" })); - GlobalVars.FaceTextureID = NovetusFuncs.GetItemTextureID(GlobalVars.UserCustomization.Face, "Face", new AssetCacheDefBasic("Decal", new string[] { "Texture" })); - - GlobalVars.TShirtTextureLocal = NovetusFuncs.GetItemTextureLocalPath(GlobalVars.TShirtTextureID, "TShirt"); - GlobalVars.ShirtTextureLocal = NovetusFuncs.GetItemTextureLocalPath(GlobalVars.ShirtTextureID, "Shirt"); - GlobalVars.PantsTextureLocal = NovetusFuncs.GetItemTextureLocalPath(GlobalVars.PantsTextureID, "Pants"); - GlobalVars.FaceTextureLocal = NovetusFuncs.GetItemTextureLocalPath(GlobalVars.FaceTextureID, "Face"); + GlobalVars.UserConfiguration.WebProxyInitialSetupRequired = WebProxySetupComplete; + GlobalVars.UserConfiguration.WebProxyEnabled = WebProxy; + NovetusFuncs.GeneratePlayerID(); + ResetCustomizationValues(); } - } - public static void CreateAssetCacheDirectories() - { - if (!Directory.Exists(GlobalPaths.AssetCacheDirAssets)) + public static void ResetCustomizationValues() { - Directory.CreateDirectory(GlobalPaths.AssetCacheDirAssets); + GlobalVars.UserCustomization = new FileFormat.CustomizationConfig(); + ReloadLoadoutValue(); } - } - public static void CreateInitialFileListIfNeededMulti() - { - if (GlobalVars.NoFileList) - return; - - string filePath = GlobalPaths.ConfigDir + "\\InitialFileList.txt"; - - if (!File.Exists(filePath)) + public static void ReloadLoadoutValue(bool localizeOnlineClothing = false) { - Util.ConsolePrint("WARNING - No file list detected. Generating Initial File List.", 5); - Thread t = new Thread(CreateInitialFileList); - t.IsBackground = true; - t.Start(); - } - else - { - int lineCount = File.ReadLines(filePath).Count(); - int fileCount = 0; + string hat1 = (!GlobalVars.UserCustomization.Hat1.EndsWith("-Solo.rbxm")) ? GlobalVars.UserCustomization.Hat1 : "NoHat.rbxm"; + string hat2 = (!GlobalVars.UserCustomization.Hat2.EndsWith("-Solo.rbxm")) ? GlobalVars.UserCustomization.Hat2 : "NoHat.rbxm"; + string hat3 = (!GlobalVars.UserCustomization.Hat3.EndsWith("-Solo.rbxm")) ? GlobalVars.UserCustomization.Hat3 : "NoHat.rbxm"; + string extra = (!GlobalVars.UserCustomization.Extra.EndsWith("-Solo.rbxm")) ? GlobalVars.UserCustomization.Extra : "NoExtra.rbxm"; - string filterPath = GlobalPaths.ConfigDir + @"\\" + GlobalPaths.InitialFileListIgnoreFilterName; - string[] fileListToIgnore = File.ReadAllLines(filterPath); + GlobalVars.Loadout = "'" + hat1 + "','" + + hat2 + "','" + + hat3 + "'," + + GlobalVars.UserCustomization.HeadColorID + "," + + GlobalVars.UserCustomization.TorsoColorID + "," + + GlobalVars.UserCustomization.LeftArmColorID + "," + + GlobalVars.UserCustomization.RightArmColorID + "," + + GlobalVars.UserCustomization.LeftLegColorID + "," + + GlobalVars.UserCustomization.RightLegColorID + ",'" + + GlobalVars.UserCustomization.TShirt + "','" + + GlobalVars.UserCustomization.Shirt + "','" + + GlobalVars.UserCustomization.Pants + "','" + + GlobalVars.UserCustomization.Face + "','" + + GlobalVars.UserCustomization.Head + "','" + + GlobalVars.UserCustomization.Icon + "','" + + extra + "'"; - DirectoryInfo dinfo = new DirectoryInfo(GlobalPaths.RootPath); - FileInfo[] Files = dinfo.GetFiles("*.*", SearchOption.AllDirectories); - foreach (FileInfo file in Files) + GlobalVars.soloLoadout = "'" + GlobalVars.UserCustomization.Hat1 + "','" + + GlobalVars.UserCustomization.Hat2 + "','" + + GlobalVars.UserCustomization.Hat3 + "'," + + GlobalVars.UserCustomization.HeadColorID + "," + + GlobalVars.UserCustomization.TorsoColorID + "," + + GlobalVars.UserCustomization.LeftArmColorID + "," + + GlobalVars.UserCustomization.RightArmColorID + "," + + GlobalVars.UserCustomization.LeftLegColorID + "," + + GlobalVars.UserCustomization.RightLegColorID + ",'" + + GlobalVars.UserCustomization.TShirt + "','" + + GlobalVars.UserCustomization.Shirt + "','" + + GlobalVars.UserCustomization.Pants + "','" + + GlobalVars.UserCustomization.Face + "','" + + GlobalVars.UserCustomization.Head + "','" + + GlobalVars.UserCustomization.Icon + "','" + + GlobalVars.UserCustomization.Extra + "'"; + + if (localizeOnlineClothing) { - DirectoryInfo localdinfo = new DirectoryInfo(file.DirectoryName); - string directory = localdinfo.Name; - if (!fileListToIgnore.Contains(file.Name, StringComparer.InvariantCultureIgnoreCase) && !fileListToIgnore.Contains(directory, StringComparer.InvariantCultureIgnoreCase)) - { - fileCount++; - } - else - { - continue; - } + GlobalVars.TShirtTextureID = NovetusFuncs.GetItemTextureID(GlobalVars.UserCustomization.TShirt, "TShirt", new AssetCacheDefBasic("ShirtGraphic", new string[] { "Graphic" })); + GlobalVars.ShirtTextureID = NovetusFuncs.GetItemTextureID(GlobalVars.UserCustomization.Shirt, "Shirt", new AssetCacheDefBasic("Shirt", new string[] { "ShirtTemplate" })); + GlobalVars.PantsTextureID = NovetusFuncs.GetItemTextureID(GlobalVars.UserCustomization.Pants, "Pants", new AssetCacheDefBasic("Pants", new string[] { "PantsTemplate" })); + GlobalVars.FaceTextureID = NovetusFuncs.GetItemTextureID(GlobalVars.UserCustomization.Face, "Face", new AssetCacheDefBasic("Decal", new string[] { "Texture" })); + + GlobalVars.TShirtTextureLocal = NovetusFuncs.GetItemTextureLocalPath(GlobalVars.TShirtTextureID, "TShirt"); + GlobalVars.ShirtTextureLocal = NovetusFuncs.GetItemTextureLocalPath(GlobalVars.ShirtTextureID, "Shirt"); + GlobalVars.PantsTextureLocal = NovetusFuncs.GetItemTextureLocalPath(GlobalVars.PantsTextureID, "Pants"); + GlobalVars.FaceTextureLocal = NovetusFuncs.GetItemTextureLocalPath(GlobalVars.FaceTextureID, "Face"); } + } - //MessageBox.Show(lineCount + "\n" + fileCount); - - if (lineCount != fileCount) + public static void CreateAssetCacheDirectories() + { + if (!Directory.Exists(GlobalPaths.AssetCacheDirAssets)) { - Util.ConsolePrint("WARNING - Initial File List is not relevant to file path. Regenerating.", 5); + Directory.CreateDirectory(GlobalPaths.AssetCacheDirAssets); + } + } + + public static void CreateInitialFileListIfNeededMulti() + { + if (GlobalVars.NoFileList) + return; + + string filePath = GlobalPaths.ConfigDir + "\\InitialFileList.txt"; + + if (!File.Exists(filePath)) + { + Util.ConsolePrint("WARNING - No file list detected. Generating Initial File List.", 5); Thread t = new Thread(CreateInitialFileList); t.IsBackground = true; t.Start(); } - } - } - - private static void CreateInitialFileList() - { - string filterPath = GlobalPaths.ConfigDir + @"\\" + GlobalPaths.InitialFileListIgnoreFilterName; - string[] fileListToIgnore = File.ReadAllLines(filterPath); - string FileName = GlobalPaths.ConfigDir + "\\InitialFileList.txt"; - - File.Create(FileName).Close(); - - using (var txt = File.CreateText(FileName)) - { - DirectoryInfo dinfo = new DirectoryInfo(GlobalPaths.RootPath); - FileInfo[] Files = dinfo.GetFiles("*.*", SearchOption.AllDirectories); - foreach (FileInfo file in Files) + else { - DirectoryInfo localdinfo = new DirectoryInfo(file.DirectoryName); - string directory = localdinfo.Name; - if (!fileListToIgnore.Contains(file.Name, StringComparer.InvariantCultureIgnoreCase) && !fileListToIgnore.Contains(directory, StringComparer.InvariantCultureIgnoreCase)) + int lineCount = File.ReadLines(filePath).Count(); + int fileCount = 0; + + string filterPath = GlobalPaths.ConfigDir + @"\\" + GlobalPaths.InitialFileListIgnoreFilterName; + string[] fileListToIgnore = File.ReadAllLines(filterPath); + + DirectoryInfo dinfo = new DirectoryInfo(GlobalPaths.RootPath); + FileInfo[] Files = dinfo.GetFiles("*.*", SearchOption.AllDirectories); + foreach (FileInfo file in Files) { - txt.WriteLine(file.FullName); + DirectoryInfo localdinfo = new DirectoryInfo(file.DirectoryName); + string directory = localdinfo.Name; + if (!fileListToIgnore.Contains(file.Name, StringComparer.InvariantCultureIgnoreCase) && !fileListToIgnore.Contains(directory, StringComparer.InvariantCultureIgnoreCase)) + { + fileCount++; + } + else + { + continue; + } } - else + + //MessageBox.Show(lineCount + "\n" + fileCount); + + if (lineCount != fileCount) { - continue; + Util.ConsolePrint("WARNING - Initial File List is not relevant to file path. Regenerating.", 5); + Thread t = new Thread(CreateInitialFileList); + t.IsBackground = true; + t.Start(); } } } - Util.ConsolePrint("File list generation finished.", 4); + private static void CreateInitialFileList() + { + string filterPath = GlobalPaths.ConfigDir + @"\\" + GlobalPaths.InitialFileListIgnoreFilterName; + string[] fileListToIgnore = File.ReadAllLines(filterPath); + string FileName = GlobalPaths.ConfigDir + "\\InitialFileList.txt"; + + File.Create(FileName).Close(); + + using (var txt = File.CreateText(FileName)) + { + DirectoryInfo dinfo = new DirectoryInfo(GlobalPaths.RootPath); + FileInfo[] Files = dinfo.GetFiles("*.*", SearchOption.AllDirectories); + foreach (FileInfo file in Files) + { + DirectoryInfo localdinfo = new DirectoryInfo(file.DirectoryName); + string directory = localdinfo.Name; + if (!fileListToIgnore.Contains(file.Name, StringComparer.InvariantCultureIgnoreCase) && !fileListToIgnore.Contains(directory, StringComparer.InvariantCultureIgnoreCase)) + { + txt.WriteLine(file.FullName); + } + else + { + continue; + } + } + } + + Util.ConsolePrint("File list generation finished.", 4); + } } -} -#endregion \ No newline at end of file + #endregion +} \ No newline at end of file diff --git a/Novetus/NovetusCore/StorageAndFunctions/GlobalPaths.cs b/Novetus/NovetusCore/StorageAndFunctions/GlobalPaths.cs index bb357f5..6373c1f 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/GlobalPaths.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/GlobalPaths.cs @@ -3,116 +3,121 @@ using System.IO; using System.Reflection; #endregion -#region Global Paths - -public class GlobalPaths +namespace Novetus.Core { - #region Base Game Paths - public static readonly string RootPathLauncher = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - public static readonly string BasePathLauncher = RootPathLauncher.Replace(@"\", @"\\"); - public static readonly string RootPath = Directory.GetParent(RootPathLauncher).ToString(); - public static readonly string BasePath = RootPath.Replace(@"\", @"\\"); - public static readonly string DataPath = BasePath + @"\\shareddata"; - public static readonly string BinDir = BasePath + @"\\bin"; - public static readonly string ConfigDir = BasePath + @"\\config"; - public static readonly string LogDir = BasePath + @"\\logs"; - public static readonly string ConfigDirClients = ConfigDir + @"\\clients"; - public static readonly string ConfigDirTemplates = ConfigDir + @"\\itemtemplates"; - public static readonly string DataDir = BinDir + @"\\data"; - public static readonly string ClientDir = BasePath + @"\\clients"; - public static readonly string MapsDir = BasePath + @"\\maps"; - public static readonly string AddonDir = BasePath + @"\\addons"; - public static readonly string AddonCoreDir = AddonDir + @"\\core"; - public static readonly string MapsDirCustom = MapsDir + @"\\Custom"; - public static readonly string MapsDirBase = "maps"; - public static readonly string BaseGameDir = "rbxasset://../../../"; - public static readonly string AltBaseGameDir = "rbxasset://"; - public static readonly string SharedDataGameDir = BaseGameDir + "shareddata/"; - #endregion + #region Global Paths - #region Customization Paths - public static readonly string CustomPlayerDir = DataPath + "\\charcustom"; - public static readonly string hatdir = CustomPlayerDir + "\\hats"; - public static readonly string facedir = CustomPlayerDir + "\\faces"; - public static readonly string headdir = CustomPlayerDir + "\\heads"; - public static readonly string tshirtdir = CustomPlayerDir + "\\tshirts"; - public static readonly string shirtdir = CustomPlayerDir + "\\shirts"; - public static readonly string pantsdir = CustomPlayerDir + "\\pants"; - public static readonly string extradir = CustomPlayerDir + "\\custom"; - public static readonly string extradirIcons = extradir + "\\icons"; + public class GlobalPaths + { + #region Base Game Paths + public static readonly string RootPathLauncher = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + public static readonly string BasePathLauncher = RootPathLauncher.Replace(@"\", @"\\"); + public static readonly string RootPath = Directory.GetParent(RootPathLauncher).ToString(); + public static readonly string BasePath = RootPath.Replace(@"\", @"\\"); + public static readonly string DataPath = BasePath + @"\\shareddata"; + public static readonly string BinDir = BasePath + @"\\bin"; + public static readonly string ConfigDir = BasePath + @"\\config"; + public static readonly string LogDir = BasePath + @"\\logs"; + public static readonly string ConfigDirClients = ConfigDir + @"\\clients"; + public static readonly string ConfigDirTemplates = ConfigDir + @"\\itemtemplates"; + public static readonly string DataDir = BinDir + @"\\data"; + public static readonly string ClientDir = BasePath + @"\\clients"; + public static readonly string MapsDir = BasePath + @"\\maps"; + public static readonly string AddonDir = BasePath + @"\\addons"; + public static readonly string AddonCoreDir = AddonDir + @"\\core"; + public static readonly string AddonNovetusExts = AddonDir + @"\\novetusexts"; + public static readonly string NovetusExtsWebProxy = AddonNovetusExts + @"\\webproxy"; + public static readonly string MapsDirCustom = MapsDir + @"\\Custom"; + public static readonly string MapsDirBase = "maps"; + public static readonly string BaseGameDir = "rbxasset://../../../"; + public static readonly string AltBaseGameDir = "rbxasset://"; + public static readonly string SharedDataGameDir = BaseGameDir + "shareddata/"; + #endregion - public static readonly string CharCustomGameDir = SharedDataGameDir + "charcustom/"; - public static readonly string hatGameDir = CharCustomGameDir + "hats/"; - public static readonly string faceGameDir = CharCustomGameDir + "faces/"; - public static readonly string headGameDir = CharCustomGameDir + "heads/"; - public static readonly string tshirtGameDir = CharCustomGameDir + "tshirts/"; - public static readonly string shirtGameDir = CharCustomGameDir + "shirts/"; - public static readonly string pantsGameDir = CharCustomGameDir + "pants/"; - public static readonly string extraGameDir = CharCustomGameDir + "custom/"; - #endregion + #region Customization Paths + public static readonly string CustomPlayerDir = DataPath + "\\charcustom"; + public static readonly string hatdir = CustomPlayerDir + "\\hats"; + public static readonly string facedir = CustomPlayerDir + "\\faces"; + public static readonly string headdir = CustomPlayerDir + "\\heads"; + public static readonly string tshirtdir = CustomPlayerDir + "\\tshirts"; + public static readonly string shirtdir = CustomPlayerDir + "\\shirts"; + public static readonly string pantsdir = CustomPlayerDir + "\\pants"; + public static readonly string extradir = CustomPlayerDir + "\\custom"; + public static readonly string extradirIcons = extradir + "\\icons"; - #region Asset Cache Paths + public static readonly string CharCustomGameDir = SharedDataGameDir + "charcustom/"; + public static readonly string hatGameDir = CharCustomGameDir + "hats/"; + public static readonly string faceGameDir = CharCustomGameDir + "faces/"; + public static readonly string headGameDir = CharCustomGameDir + "heads/"; + public static readonly string tshirtGameDir = CharCustomGameDir + "tshirts/"; + public static readonly string shirtGameDir = CharCustomGameDir + "shirts/"; + public static readonly string pantsGameDir = CharCustomGameDir + "pants/"; + public static readonly string extraGameDir = CharCustomGameDir + "custom/"; + #endregion - #region Base Paths - public static readonly string DirFonts = "\\fonts"; - public static readonly string DirSounds = "\\sounds"; - public static readonly string DirTextures = "\\textures"; - public static readonly string DirScripts = "\\scripts"; - public static readonly string FontsGameDir = "fonts/"; - public static readonly string SoundsGameDir = "sounds/"; - public static readonly string TexturesGameDir = "textures/"; - public static readonly string ScriptsGameDir = "scripts/"; - #endregion + #region Asset Cache Paths - #region Asset Dirs - public static string AssetCacheDir = DataPath + "\\assetcache"; - public static string AssetCacheDirAssets = AssetCacheDir + "\\assets"; + #region Base Paths + public static readonly string DirFonts = "\\fonts"; + public static readonly string DirSounds = "\\sounds"; + public static readonly string DirTextures = "\\textures"; + public static readonly string DirScripts = "\\scripts"; + public static readonly string FontsGameDir = "fonts/"; + public static readonly string SoundsGameDir = "sounds/"; + public static readonly string TexturesGameDir = "textures/"; + public static readonly string ScriptsGameDir = "scripts/"; + #endregion - public static string AssetCacheGameDir = SharedDataGameDir + "assetcache/"; - public static string AssetCacheAssetsGameDir = AssetCacheGameDir + "assets/"; - #endregion + #region Asset Dirs + public static string AssetCacheDir = DataPath + "\\assetcache"; + public static string AssetCacheDirAssets = AssetCacheDir + "\\assets"; - #region Item Dirs - public static readonly string hatdirFonts = hatdir + DirFonts; - public static readonly string hatdirTextures = hatdir + DirTextures; - public static readonly string hatdirSounds = hatdir + DirSounds; - public static readonly string hatdirScripts = hatdir + DirScripts; - public static readonly string facedirTextures = facedir; //+ DirTextures; - public static readonly string headdirFonts = headdir + DirFonts; - public static readonly string headdirTextures = headdir + DirTextures; - public static readonly string tshirtdirTextures = tshirtdir; //+ DirTextures; - public static readonly string shirtdirTextures = shirtdir + DirTextures; - public static readonly string pantsdirTextures = pantsdir + DirTextures; + public static string AssetCacheGameDir = SharedDataGameDir + "assetcache/"; + public static string AssetCacheAssetsGameDir = AssetCacheGameDir + "assets/"; + #endregion - public static readonly string hatGameDirFonts = hatGameDir + FontsGameDir; - public static readonly string hatGameDirTextures = hatGameDir + TexturesGameDir; - public static readonly string hatGameDirSounds = hatGameDir + SoundsGameDir; - public static readonly string hatGameDirScripts = hatGameDir + ScriptsGameDir; - public static readonly string faceGameDirTextures = faceGameDir; //+ TexturesGameDir; - public static readonly string headGameDirFonts = headGameDir + FontsGameDir; - public static readonly string headGameDirTextures = headGameDir + TexturesGameDir; - public static readonly string tshirtGameDirTextures = tshirtGameDir; //+ TexturesGameDir; - public static readonly string shirtGameDirTextures = shirtGameDir + TexturesGameDir; - public static readonly string pantsGameDirTextures = pantsGameDir + TexturesGameDir; - #endregion + #region Item Dirs + public static readonly string hatdirFonts = hatdir + DirFonts; + public static readonly string hatdirTextures = hatdir + DirTextures; + public static readonly string hatdirSounds = hatdir + DirSounds; + public static readonly string hatdirScripts = hatdir + DirScripts; + public static readonly string facedirTextures = facedir; //+ DirTextures; + public static readonly string headdirFonts = headdir + DirFonts; + public static readonly string headdirTextures = headdir + DirTextures; + public static readonly string tshirtdirTextures = tshirtdir; //+ DirTextures; + public static readonly string shirtdirTextures = shirtdir + DirTextures; + public static readonly string pantsdirTextures = pantsdir + DirTextures; - #endregion + public static readonly string hatGameDirFonts = hatGameDir + FontsGameDir; + public static readonly string hatGameDirTextures = hatGameDir + TexturesGameDir; + public static readonly string hatGameDirSounds = hatGameDir + SoundsGameDir; + public static readonly string hatGameDirScripts = hatGameDir + ScriptsGameDir; + public static readonly string faceGameDirTextures = faceGameDir; //+ TexturesGameDir; + public static readonly string headGameDirFonts = headGameDir + FontsGameDir; + public static readonly string headGameDirTextures = headGameDir + TexturesGameDir; + public static readonly string tshirtGameDirTextures = tshirtGameDir; //+ TexturesGameDir; + public static readonly string shirtGameDirTextures = shirtGameDir + TexturesGameDir; + public static readonly string pantsGameDirTextures = pantsGameDir + TexturesGameDir; + #endregion - #region File Names - public static readonly string ConfigName = "config.ini"; - public static string ConfigNameCustomization = "config_customization.ini"; - public static readonly string InfoName = "info.ini"; - public static readonly string ScriptName = "CSMPFunctions"; - public static readonly string ScriptGenName = "CSMPBoot"; - public static readonly string ContentProviderXMLName = "ContentProviders.xml"; - public static readonly string PartColorXMLName = "PartColors.xml"; - public static readonly string FileDeleteFilterName = "FileDeleteFilter.txt"; - public static readonly string InitialFileListIgnoreFilterName = "InitialFileListIgnoreFilter.txt"; - public static readonly string ServerInfoFileName = "serverinfo.txt"; - public static readonly string ConsoleHelpFileName = "consolehelp.txt"; - public static readonly string ClientScriptDocumentationFileName = "documentation.txt"; - public static readonly string AddonLoaderFileName = "AddonLoader.lua"; - public static readonly string AssetFixerPatternFileName = "assetfixer_pattern.txt"; + #endregion + + #region File Names + public static readonly string ConfigName = "config.ini"; + public static string ConfigNameCustomization = "config_customization.ini"; + public static readonly string InfoName = "info.ini"; + public static readonly string ScriptName = "CSMPFunctions"; + public static readonly string ScriptGenName = "CSMPBoot"; + public static readonly string ContentProviderXMLName = "ContentProviders.xml"; + public static readonly string PartColorXMLName = "PartColors.xml"; + public static readonly string FileDeleteFilterName = "FileDeleteFilter.txt"; + public static readonly string InitialFileListIgnoreFilterName = "InitialFileListIgnoreFilter.txt"; + public static readonly string ServerInfoFileName = "serverinfo.txt"; + public static readonly string ConsoleHelpFileName = "consolehelp.txt"; + public static readonly string ClientScriptDocumentationFileName = "documentation.txt"; + public static readonly string AddonLoaderFileName = "AddonLoader.lua"; + public static readonly string AssetFixerPatternFileName = "assetfixer_pattern.txt"; + #endregion + } #endregion } -#endregion diff --git a/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs b/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs index bf0ea19..1f7d1dd 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs @@ -14,140 +14,143 @@ using System.Diagnostics; using System.Windows.Forms; #endregion -#region Script Type -public enum ScriptType +namespace Novetus.Core { - Client = 0, - Server = 1, - Solo = 2, - Studio = 3, - EasterEgg = 4, - None = 5 -} -#endregion - -#region Game Server Definition -public class GameServer -{ - public GameServer(string ip, int port) + #region Script Type + public enum ScriptType { - ServerIP = ip; - ServerPort = port; + Client = 0, + Server = 1, + Solo = 2, + Studio = 3, + EasterEgg = 4, + None = 5 } + #endregion - public override string ToString() - { - return ServerIP + ":" + ServerPort.ToString(); - } - - public void SetValues(string input) + #region Game Server Definition + public class GameServer { - try + public GameServer(string ip, int port) { - string[] vals = input.Split(':'); - string ip = vals[0]; - int port = Convert.ToInt32(vals[1]); - ServerIP = ip; ServerPort = port; } - catch (Exception) + + public override string ToString() { - ServerIP = input; - ServerPort = GlobalVars.DefaultRobloxPort; + return ServerIP + ":" + ServerPort.ToString(); } + + public void SetValues(string input) + { + try + { + string[] vals = input.Split(':'); + string ip = vals[0]; + int port = Convert.ToInt32(vals[1]); + + ServerIP = ip; + ServerPort = port; + } + catch (Exception) + { + ServerIP = input; + ServerPort = GlobalVars.DefaultRobloxPort; + } + } + + public string ServerIP { get; set; } + public int ServerPort { get; set; } } + #endregion - public string ServerIP { get; set; } - public int ServerPort { get; set; } -} -#endregion - -#region Global Variables -public static class GlobalVars -{ - #region Discord - public enum LauncherState + #region Global Variables + public static class GlobalVars { - InLauncher = 0, - InMPGame = 1, - InSoloGame = 2, - InStudio = 3, - InCustomization = 4, - InEasterEggGame = 5, - LoadingURI = 6 - } + #region Discord + public enum LauncherState + { + InLauncher = 0, + InMPGame = 1, + InSoloGame = 2, + InStudio = 3, + InCustomization = 4, + InEasterEggGame = 5, + LoadingURI = 6 + } - public static DiscordRPC.EventHandlers handlers; - #endregion + public static DiscordRPC.EventHandlers handlers; + #endregion - #region Class definitions - public static FileFormat.ProgramInfo ProgramInformation = new FileFormat.ProgramInfo(); - public static FileFormat.Config UserConfiguration = new FileFormat.Config(); - public static FileFormat.ClientInfo SelectedClientInfo = new FileFormat.ClientInfo(); - public static FileFormat.CustomizationConfig UserCustomization = new FileFormat.CustomizationConfig(); - public static PartColor[] PartColorList; - public static List PartColorListConv; - #endregion + #region Class definitions + public static FileFormat.ProgramInfo ProgramInformation = new FileFormat.ProgramInfo(); + public static FileFormat.Config UserConfiguration = new FileFormat.Config(); + public static FileFormat.ClientInfo SelectedClientInfo = new FileFormat.ClientInfo(); + public static FileFormat.CustomizationConfig UserCustomization = new FileFormat.CustomizationConfig(); + public static PartColor[] PartColorList; + public static List PartColorListConv; + #endregion - #region Joining/Hosting - public static string DefaultIP = "localhost"; - public static int DefaultRobloxPort = 53640; - public static GameServer CurrentServer = new GameServer(DefaultIP, DefaultRobloxPort); - public static string ExternalIP = SecurityFuncs.GetExternalIPAddress(); - public static ScriptType GameOpened = ScriptType.None; - public static string PlayerTripcode = ""; + #region Joining/Hosting + public static string DefaultIP = "localhost"; + public static int DefaultRobloxPort = 53640; + public static GameServer CurrentServer = new GameServer(DefaultIP, DefaultRobloxPort); + public static string ExternalIP = SecurityFuncs.GetExternalIPAddress(); + public static ScriptType GameOpened = ScriptType.None; + public static string PlayerTripcode = ""; #if LAUNCHER || URI - public static int WebProxyPort = 0; - public static WebProxy Proxy = new WebProxy(); + public static int WebProxyPort = 0; + public static WebProxy Proxy = new WebProxy(); #endif -#endregion + #endregion #if LAUNCHER - #region Novetus Launcher + #region Novetus Launcher public static NovetusLauncher.NovetusConsole consoleForm = null; - #endregion + #endregion #endif - #region Customization - public static string Loadout = ""; - public static string soloLoadout = ""; - public static string TShirtTextureID = ""; - public static string ShirtTextureID = ""; - public static string PantsTextureID = ""; - public static string FaceTextureID = ""; - public static string TShirtTextureLocal = ""; - public static string ShirtTextureLocal = ""; - public static string PantsTextureLocal = ""; - public static string FaceTextureLocal = ""; - #endregion + #region Customization + public static string Loadout = ""; + public static string soloLoadout = ""; + public static string TShirtTextureID = ""; + public static string ShirtTextureID = ""; + public static string PantsTextureID = ""; + public static string FaceTextureID = ""; + public static string TShirtTextureLocal = ""; + public static string ShirtTextureLocal = ""; + public static string PantsTextureLocal = ""; + public static string FaceTextureLocal = ""; + #endregion - #region Discord Variables - //discord - public static DiscordRPC.RichPresence presence; - public static string appid = "505955125727330324"; - public static string imagekey_large = "novetus_large"; - public static string image_ingame = "ingame_small"; - public static string image_inlauncher = "inlauncher_small"; - public static string image_instudio = "instudio_small"; - public static string image_incustomization = "incustomization_small"; - #endregion + #region Discord Variables + //discord + public static DiscordRPC.RichPresence presence; + public static string appid = "505955125727330324"; + public static string imagekey_large = "novetus_large"; + public static string image_ingame = "ingame_small"; + public static string image_inlauncher = "inlauncher_small"; + public static string image_instudio = "instudio_small"; + public static string image_incustomization = "incustomization_small"; + #endregion - #region Other - public static bool ExtendedVersionNumber = false; - public static bool LocalPlayMode = false; - public static bool AdminMode = false; - public static bool ColorsLoaded = false; - public static int ValidatedExtraFiles = 0; - public static bool NoFileList = false; - public static string ServerID = "N/A"; - public static string PingURL = ""; - public static string Important = ""; - public static string Important2 = ""; - public static string NextCommand = ""; - public static bool AppClosed = false; - public static bool isConsoleOnly = false; - public static bool isMapCompressed = false; + #region Other + public static bool ExtendedVersionNumber = false; + public static bool LocalPlayMode = false; + public static bool AdminMode = false; + public static bool ColorsLoaded = false; + public static int ValidatedExtraFiles = 0; + public static bool NoFileList = false; + public static string ServerID = "N/A"; + public static string PingURL = ""; + public static string Important = ""; + public static string Important2 = ""; + public static string NextCommand = ""; + public static bool AppClosed = false; + public static bool isConsoleOnly = false; + public static bool isMapCompressed = false; + #endregion + } #endregion } -#endregion diff --git a/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs b/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs index dfd2057..7695849 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs @@ -4,50 +4,53 @@ using Mono.Nat; using System; #endregion -#region NetFuncs - -public static class NetFuncs +namespace Novetus.Core { - public static void InitUPnP(EventHandler DeviceFound, EventHandler DeviceLost) - { - if (GlobalVars.UserConfiguration.UPnP) - { - NatUtility.DeviceFound += DeviceFound; - NatUtility.StartDiscovery(); - } - } + #region NetFuncs - public static void StartUPnP(INatDevice device, Protocol protocol, int port) + public static class NetFuncs { - if (GlobalVars.UserConfiguration.UPnP) + public static void InitUPnP(EventHandler DeviceFound, EventHandler DeviceLost) { - Mapping checker = device.GetSpecificMapping(protocol, port); - int mapPublic = checker.PublicPort; - int mapPrivate = checker.PrivatePort; - - if (mapPublic == -1 && mapPrivate == -1) + if (GlobalVars.UserConfiguration.UPnP) { - Mapping portmap = new Mapping(protocol, port, port); - device.CreatePortMap(portmap); - } - } - } - - public static void StopUPnP(INatDevice device, Protocol protocol, int port) - { - if (GlobalVars.UserConfiguration.UPnP) - { - Mapping checker = device.GetSpecificMapping(protocol, port); - int mapPublic = checker.PublicPort; - int mapPrivate = checker.PrivatePort; - - if (mapPublic != -1 && mapPrivate != -1) - { - Mapping portmap = new Mapping(protocol, port, port); - device.DeletePortMap(portmap); + NatUtility.DeviceFound += DeviceFound; + NatUtility.StartDiscovery(); + } + } + + public static void StartUPnP(INatDevice device, Protocol protocol, int port) + { + if (GlobalVars.UserConfiguration.UPnP) + { + Mapping checker = device.GetSpecificMapping(protocol, port); + int mapPublic = checker.PublicPort; + int mapPrivate = checker.PrivatePort; + + if (mapPublic == -1 && mapPrivate == -1) + { + Mapping portmap = new Mapping(protocol, port, port); + device.CreatePortMap(portmap); + } + } + } + + public static void StopUPnP(INatDevice device, Protocol protocol, int port) + { + if (GlobalVars.UserConfiguration.UPnP) + { + Mapping checker = device.GetSpecificMapping(protocol, port); + int mapPublic = checker.PublicPort; + int mapPrivate = checker.PrivatePort; + + if (mapPublic != -1 && mapPrivate != -1) + { + Mapping portmap = new Mapping(protocol, port, port); + device.DeletePortMap(portmap); + } } } } + #endregion } -#endregion #endif diff --git a/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs b/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs index 0a5840e..dd5bb2e 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs @@ -10,188 +10,190 @@ using System.Windows.Forms; using System.Collections.Generic; #endregion -#region Novetus Functions -public class NovetusFuncs +namespace Novetus.Core { - public static string CopyMapToRBXAsset() + #region Novetus Functions + public class NovetusFuncs { - string clientcontentpath = GlobalPaths.ClientDir + @"\\" + GlobalVars.UserConfiguration.SelectedClient + @"\\content\\temp.rbxl"; - Util.FixedFileCopy(GlobalVars.UserConfiguration.MapPath, clientcontentpath, true); - return GlobalPaths.AltBaseGameDir + "temp.rbxl"; - } - - public static string GetItemTextureLocalPath(string item, string nameprefix) - { - //don't bother, we're offline. - if (GlobalVars.ExternalIP.Equals("localhost")) - return ""; - - if (!GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%localizeonlineclothing%")) - return ""; - - if (item.Contains("http://") || item.Contains("https://")) + public static string CopyMapToRBXAsset() { - string peram = "id="; - string fullname = nameprefix + "Temp.png"; + string clientcontentpath = GlobalPaths.ClientDir + @"\\" + GlobalVars.UserConfiguration.SelectedClient + @"\\content\\temp.rbxl"; + Util.FixedFileCopy(GlobalVars.UserConfiguration.MapPath, clientcontentpath, true); + return GlobalPaths.AltBaseGameDir + "temp.rbxl"; + } - if (item.Contains(peram)) + public static string GetItemTextureLocalPath(string item, string nameprefix) + { + //don't bother, we're offline. + if (GlobalVars.ExternalIP.Equals("localhost")) + return ""; + + if (!GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%localizeonlineclothing%")) + return ""; + + if (item.Contains("http://") || item.Contains("https://")) { - string id = item.After(peram); - fullname = id + ".png"; + string peram = "id="; + string fullname = nameprefix + "Temp.png"; + + if (item.Contains(peram)) + { + string id = item.After(peram); + fullname = id + ".png"; + } + else + { + return item; + } + + Downloader download = new Downloader(item, fullname, "", GlobalPaths.AssetCacheDirAssets); + + try + { + string path = download.GetFullDLPath(); + download.InitDownloadNoDialog(path); + return GlobalPaths.AssetCacheAssetsGameDir + download.fileName; + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); +#else + catch (Exception) + { +#endif + } + } + + return ""; + } + + public static string GetItemTextureID(string item, string name, AssetCacheDefBasic assetCacheDef) + { + //don't bother, we're offline. + if (GlobalVars.ExternalIP.Equals("localhost")) + return ""; + + if (!GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%localizeonlineclothing%")) + return ""; + + if (item.Contains("http://") || item.Contains("https://")) + { + string peram = "id="; + if (!item.Contains(peram)) + { + return item; + } + + Downloader download = new Downloader(item, name + "Temp.rbxm", "", GlobalPaths.AssetCacheDirAssets); + + try + { + string path = download.GetFullDLPath(); + download.InitDownloadNoDialog(path); + string oldfile = File.ReadAllText(path); + string fixedfile = RobloxXML.RemoveInvalidXmlChars(RobloxXML.ReplaceHexadecimalSymbols(oldfile)).Replace(" ", "\t").Replace("#9;", "\t"); + XDocument doc = null; + XmlReaderSettings xmlReaderSettings = new XmlReaderSettings { CheckCharacters = false }; + Stream filestream = Util.GenerateStreamFromString(fixedfile); + using (XmlReader xmlReader = XmlReader.Create(filestream, xmlReaderSettings)) + { + xmlReader.MoveToContent(); + doc = XDocument.Load(xmlReader); + } + + return RobloxXML.GetURLInNodes(doc, assetCacheDef.Class, assetCacheDef.Id[0], item); + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); +#else + catch (Exception) + { +#endif + } + } + + return ""; + } + + public static void GeneratePlayerID() + { + int randomID = SecurityFuncs.GenerateRandomNumber(); + //2147483647 is max id. + GlobalVars.UserConfiguration.UserID = randomID; + } + + public static string GenerateAndReturnTripcode() + { + //Powered by https://github.com/davcs86/csharp-uhwid + return UHWIDEngine.AdvancedUid; + } + + public static void PingMasterServer(bool online, string reason) + { + if (online) + { + GlobalVars.ServerID = SecurityFuncs.RandomString(30) + SecurityFuncs.GenerateRandomNumber(); + GlobalVars.PingURL = "http://" + GlobalVars.UserConfiguration.ServerBrowserServerAddress + + "/list.php?name=" + GlobalVars.UserConfiguration.ServerBrowserServerName + + "&ip=" + (!string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : GlobalVars.ExternalIP) + + "&port=" + GlobalVars.UserConfiguration.RobloxPort + + "&client=" + GlobalVars.UserConfiguration.SelectedClient + + "&version=" + GlobalVars.ProgramInformation.Version + + "&id=" + GlobalVars.ServerID; } else { - return item; - } - - Downloader download = new Downloader(item, fullname, "", GlobalPaths.AssetCacheDirAssets); - - try - { - string path = download.GetFullDLPath(); - download.InitDownloadNoDialog(path); - return GlobalPaths.AssetCacheAssetsGameDir + download.fileName; - } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif - } - } - - return ""; - } - - public static string GetItemTextureID(string item, string name, AssetCacheDefBasic assetCacheDef) - { - //don't bother, we're offline. - if (GlobalVars.ExternalIP.Equals("localhost")) - return ""; - - if (!GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%localizeonlineclothing%")) - return ""; - - if (item.Contains("http://") || item.Contains("https://")) - { - string peram = "id="; - if (!item.Contains(peram)) - { - return item; - } - - Downloader download = new Downloader(item, name + "Temp.rbxm", "", GlobalPaths.AssetCacheDirAssets); - - try - { - string path = download.GetFullDLPath(); - download.InitDownloadNoDialog(path); - string oldfile = File.ReadAllText(path); - string fixedfile = RobloxXML.RemoveInvalidXmlChars(RobloxXML.ReplaceHexadecimalSymbols(oldfile)).Replace(" ", "\t").Replace("#9;", "\t"); - XDocument doc = null; - XmlReaderSettings xmlReaderSettings = new XmlReaderSettings { CheckCharacters = false }; - Stream filestream = Util.GenerateStreamFromString(fixedfile); - using (XmlReader xmlReader = XmlReader.Create(filestream, xmlReaderSettings)) - { - xmlReader.MoveToContent(); - doc = XDocument.Load(xmlReader); - } - - return RobloxXML.GetURLInNodes(doc, assetCacheDef.Class, assetCacheDef.Id[0], item); - } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif - } - } - - return ""; - } - - public static void GeneratePlayerID() - { - int randomID = SecurityFuncs.GenerateRandomNumber(); - //2147483647 is max id. - GlobalVars.UserConfiguration.UserID = randomID; - } - - public static string GenerateAndReturnTripcode() - { - //Powered by https://github.com/davcs86/csharp-uhwid - return UHWID.UHWIDEngine.AdvancedUid; - } - - public static void PingMasterServer(bool online, string reason) - { - if (online) - { - GlobalVars.ServerID = SecurityFuncs.RandomString(30) + SecurityFuncs.GenerateRandomNumber(); - GlobalVars.PingURL = "http://" + GlobalVars.UserConfiguration.ServerBrowserServerAddress + - "/list.php?name=" + GlobalVars.UserConfiguration.ServerBrowserServerName + - "&ip=" + (!string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : GlobalVars.ExternalIP) + - "&port=" + GlobalVars.UserConfiguration.RobloxPort + - "&client=" + GlobalVars.UserConfiguration.SelectedClient + - "&version=" + GlobalVars.ProgramInformation.Version + - "&id=" + GlobalVars.ServerID; - } - else - { - GlobalVars.PingURL = "http://" + GlobalVars.UserConfiguration.ServerBrowserServerAddress + - "/delist.php?id=" + GlobalVars.ServerID; - GlobalVars.ServerID = "N/A"; - } - - Util.ConsolePrint("Pinging master server. " + reason, 4); - Task.Factory.StartNew(() => TryPing()); - } - - private static void TryPing() - { - string response = Util.HttpGet(GlobalVars.PingURL); - - if (!string.IsNullOrWhiteSpace(response)) - { - Util.ConsolePrint(response, response.Contains("ERROR:") ? 2 : 4); - - if (response.Contains("ERROR:")) - { + GlobalVars.PingURL = "http://" + GlobalVars.UserConfiguration.ServerBrowserServerAddress + + "/delist.php?id=" + GlobalVars.ServerID; GlobalVars.ServerID = "N/A"; } + + Util.ConsolePrint("Pinging master server. " + reason, 4); + Task.Factory.StartNew(() => TryPing()); } - if (!GlobalVars.ServerID.Equals("N/A")) + private static void TryPing() { - Util.ConsolePrint("Master server ping successful. Your server's ID is " + GlobalVars.ServerID, 4); + string response = Util.HttpGet(GlobalVars.PingURL); + + if (!string.IsNullOrWhiteSpace(response)) + { + Util.ConsolePrint(response, response.Contains("ERROR:") ? 2 : 4); + + if (response.Contains("ERROR:")) + { + GlobalVars.ServerID = "N/A"; + } + } + + if (!GlobalVars.ServerID.Equals("N/A")) + { + Util.ConsolePrint("Master server ping successful. Your server's ID is " + GlobalVars.ServerID, 4); + } + + GlobalVars.PingURL = ""; } - GlobalVars.PingURL = ""; - } - - public static string[] LoadServerInformation() - { - string[] lines1 = { + public static string[] LoadServerInformation() + { + string[] lines1 = { SecurityFuncs.Base64Encode(!string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : GlobalVars.ExternalIP), SecurityFuncs.Base64Encode(GlobalVars.UserConfiguration.RobloxPort.ToString()), SecurityFuncs.Base64Encode(GlobalVars.UserConfiguration.SelectedClient) }; - string URI = "novetus://" + SecurityFuncs.Base64Encode(string.Join("|", lines1), true); - string[] lines2 = { + string URI = "novetus://" + SecurityFuncs.Base64Encode(string.Join("|", lines1), true); + string[] lines2 = { SecurityFuncs.Base64Encode("localhost"), SecurityFuncs.Base64Encode(GlobalVars.UserConfiguration.RobloxPort.ToString()), SecurityFuncs.Base64Encode(GlobalVars.UserConfiguration.SelectedClient) }; - string URI2 = "novetus://" + SecurityFuncs.Base64Encode(string.Join("|", lines2), true); - GameServer server = new GameServer((!string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : GlobalVars.ExternalIP), - GlobalVars.UserConfiguration.RobloxPort); - string[] text = { + string URI2 = "novetus://" + SecurityFuncs.Base64Encode(string.Join("|", lines2), true); + GameServer server = new GameServer((!string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : GlobalVars.ExternalIP), + GlobalVars.UserConfiguration.RobloxPort); + string[] text = { "Server IP Address: " + server.ToString(), "Client: " + GlobalVars.UserConfiguration.SelectedClient, "Map: " + GlobalVars.UserConfiguration.Map, @@ -203,436 +205,449 @@ public class NovetusFuncs URI2 }; - return text; - } + return text; + } - public static void CreateTXT() - { - List text = new List(); - text.AddRange(LoadServerInformation()); + public static void CreateTXT() + { + List text = new List(); + text.AddRange(LoadServerInformation()); - string txt = GlobalPaths.BasePath + "\\" + GlobalPaths.ServerInfoFileName; - File.WriteAllLines(txt, text); - Util.ConsolePrint("Server Information sent to file " + txt, 4); - } + string txt = GlobalPaths.BasePath + "\\" + GlobalPaths.ServerInfoFileName; + File.WriteAllLines(txt, text); + Util.ConsolePrint("Server Information sent to file " + txt, 4); + } #if LAUNCHER || URI - public static void LaunchCharacterCustomization() - { - //https://stackoverflow.com/questions/9029351/close-all-open-forms-except-the-main-menu-in-c-sharp - FormCollection fc = Application.OpenForms; - - foreach (Form frm in fc) + public static void LaunchCharacterCustomization() { - //iterate through - if (frm.Name == "CharacterCustomizationExtended" || - frm.Name == "CharacterCustomizationCompact") + //https://stackoverflow.com/questions/9029351/close-all-open-forms-except-the-main-menu-in-c-sharp + FormCollection fc = Application.OpenForms; + + foreach (Form frm in fc) { - frm.Close(); - break; + //iterate through + if (frm.Name == "CharacterCustomizationExtended" || + frm.Name == "CharacterCustomizationCompact") + { + frm.Close(); + break; + } + } + + switch (GlobalVars.UserConfiguration.LauncherStyle) + { + case Settings.Style.Extended: + CharacterCustomizationExtended ccustom = new CharacterCustomizationExtended(); + ccustom.Show(); + break; + case Settings.Style.Compact: + CharacterCustomizationCompact ccustom2 = new CharacterCustomizationCompact(); + ccustom2.Show(); + break; + case Settings.Style.Stylish: + default: + CharacterCustomizationExtended ccustom3 = new CharacterCustomizationExtended(); + ccustom3.Show(); + break; } } - - switch (GlobalVars.UserConfiguration.LauncherStyle) - { - case Settings.Style.Extended: - CharacterCustomizationExtended ccustom = new CharacterCustomizationExtended(); - ccustom.Show(); - break; - case Settings.Style.Compact: - CharacterCustomizationCompact ccustom2 = new CharacterCustomizationCompact(); - ccustom2.Show(); - break; - case Settings.Style.Stylish: - default: - CharacterCustomizationExtended ccustom3 = new CharacterCustomizationExtended(); - ccustom3.Show(); - break; - } - } #endif - public static string FixURLString(string str, string str2) - { - string fixedStr = str.ToLower().Replace("?version=1&id=", "?id=") - .Replace("?version=1&id=", "?id=") - .Replace("&", "&") - .Replace("amp;", "&"); - - string baseurl = fixedStr.Before("/asset/?id="); - - if (baseurl == "") + public static string FixURLString(string str, string str2) { - baseurl = fixedStr.Before("/asset?id="); + string fixedStr = str.ToLower().Replace("?version=1&id=", "?id=") + .Replace("?version=1&id=", "?id=") + .Replace("&", "&") + .Replace("amp;", "&"); + + string baseurl = fixedStr.Before("/asset/?id="); + if (baseurl == "") { - baseurl = fixedStr.Before("/item.aspx?id="); + baseurl = fixedStr.Before("/asset?id="); + if (baseurl == "") + { + baseurl = fixedStr.Before("/item.aspx?id="); + } + } + + string fixedUrl = fixedStr.Replace(baseurl + "/asset/?id=", str2) + .Replace(baseurl + "/asset?id=", str2) + .Replace(baseurl + "/item.aspx?id=", str2); + + //...because scripts mess it up. + + string id = fixedUrl.After("id="); + if (id.Contains("&version=")) + { + string ver = id.After("&version="); + id = id.Replace("&version=" + ver, ""); + } + + string fixedID = Regex.Replace(id, "[^0-9]", ""); + + //really fucking hacky. + string finalUrl = fixedUrl.Before("id=") + "id=" + fixedID; + + return finalUrl; + } + + public static void SetupAdminPassword() + { + CryptoRandom random = new CryptoRandom(); + string Name1 = SecurityFuncs.GenerateName(random.Next(4, 12)); + string Name2 = SecurityFuncs.GenerateName(random.Next(4, 12)); + GlobalVars.Important = Name1 + Name2; + GlobalVars.Important2 = SecurityFuncs.Encipher(GlobalVars.Important, random.Next(2, 13)); + } + } + #endregion + + #region Roblox Helpers + #region Vector3 + public class Vector3 + { + public double X; + public double Y; + public double Z; + + public Vector3(double aX, double aY, double aZ) + { + X = aX; + Y = aY; + Z = aZ; + } + } + #endregion + + #region Roblox File Types + public enum RobloxFileType + { + //RBXL and RBXM + RBXL, + RBXM, + //Items + Hat, + Head, + Face, + TShirt, + Shirt, + Pants, + Script, + HeadNoCustomMesh + } + #endregion + + #region Asset Cache Definition + public class AssetCacheDefBasic + { + public AssetCacheDefBasic(string clas, string[] id) + { + Class = clas; + Id = id; + } + + public string Class { get; set; } + public string[] Id { get; set; } + } + + public class AssetCacheDef : AssetCacheDefBasic + { + public AssetCacheDef(string clas, string[] id, string[] ext, + string[] dir, string[] gamedir) : base(clas, id) + { + Ext = ext; + Dir = dir; + GameDir = gamedir; + } + + public string[] Ext { get; set; } + public string[] Dir { get; set; } + public string[] GameDir { get; set; } + } + #endregion + + #region Roblox Type Definitions + public struct RobloxDefs + { + //item defs below + public static AssetCacheDef ItemHatFonts + { + get + { + return new AssetCacheDef("SpecialMesh", + new string[] { "MeshId", "TextureId" }, + new string[] { ".mesh", ".png" }, + new string[] { GlobalPaths.hatdirFonts, GlobalPaths.hatdirTextures }, + new string[] { GlobalPaths.hatGameDirFonts, GlobalPaths.hatGameDirTextures }); } } - string fixedUrl = fixedStr.Replace(baseurl + "/asset/?id=", str2) - .Replace(baseurl + "/asset?id=", str2) - .Replace(baseurl + "/item.aspx?id=", str2); - - //...because scripts mess it up. - - string id = fixedUrl.After("id="); - if (id.Contains("&version=")) + public static AssetCacheDef ItemHatSound { - string ver = id.After("&version="); - id = id.Replace("&version=" + ver, ""); - } - - string fixedID = Regex.Replace(id, "[^0-9]", ""); - - //really fucking hacky. - string finalUrl = fixedUrl.Before("id=") + "id=" + fixedID; - - return finalUrl; - } - - public static void SetupAdminPassword() - { - CryptoRandom random = new CryptoRandom(); - string Name1 = SecurityFuncs.GenerateName(random.Next(4, 12)); - string Name2 = SecurityFuncs.GenerateName(random.Next(4, 12)); - GlobalVars.Important = Name1 + Name2; - GlobalVars.Important2 = SecurityFuncs.Encipher(GlobalVars.Important, random.Next(2, 13)); - } -} -#endregion - -#region Roblox Helpers -#region Vector3 -public class Vector3 -{ - public double X; - public double Y; - public double Z; - - public Vector3(double aX, double aY, double aZ) - { - X = aX; - Y = aY; - Z = aZ; - } -} -#endregion - -#region Roblox File Types -public enum RobloxFileType -{ - //RBXL and RBXM - RBXL, - RBXM, - //Items - Hat, - Head, - Face, - TShirt, - Shirt, - Pants, - Script, - HeadNoCustomMesh -} -#endregion - -#region Asset Cache Definition -public class AssetCacheDefBasic -{ - public AssetCacheDefBasic(string clas, string[] id) - { - Class = clas; - Id = id; - } - - public string Class { get; set; } - public string[] Id { get; set; } -} - -public class AssetCacheDef : AssetCacheDefBasic -{ - public AssetCacheDef(string clas, string[] id, string[] ext, - string[] dir, string[] gamedir) : base(clas, id) - { - Ext = ext; - Dir = dir; - GameDir = gamedir; - } - - public string[] Ext { get; set; } - public string[] Dir { get; set; } - public string[] GameDir { get; set; } -} -#endregion - -#region Roblox Type Definitions -public struct RobloxDefs -{ - //item defs below - public static AssetCacheDef ItemHatFonts - { - get - { - return new AssetCacheDef("SpecialMesh", - new string[] { "MeshId", "TextureId" }, - new string[] { ".mesh", ".png" }, - new string[] { GlobalPaths.hatdirFonts, GlobalPaths.hatdirTextures }, - new string[] { GlobalPaths.hatGameDirFonts, GlobalPaths.hatGameDirTextures }); - } - } - - public static AssetCacheDef ItemHatSound - { - get - { - return new AssetCacheDef("Sound", - new string[] { "SoundId" }, - new string[] { ".wav" }, - new string[] { GlobalPaths.hatdirSounds }, - new string[] { GlobalPaths.hatGameDirSounds }); - } - } - - public static AssetCacheDef ItemHatScript - { - get - { - return new AssetCacheDef("Script", - new string[] { "LinkedSource" }, - new string[] { ".lua" }, - new string[] { GlobalPaths.hatdirScripts }, - new string[] { GlobalPaths.hatGameDirScripts }); - } - } - - public static AssetCacheDef ItemHatLocalScript - { - get - { - return new AssetCacheDef("LocalScript", - new string[] { "LinkedSource" }, - new string[] { ".lua" }, - new string[] { GlobalPaths.hatdirScripts }, - new string[] { GlobalPaths.hatGameDirScripts }); - } - } - - public static AssetCacheDef ItemHeadFonts - { - get - { - return new AssetCacheDef("SpecialMesh", - new string[] { "MeshId", "TextureId" }, - new string[] { ".mesh", ".png" }, - new string[] { GlobalPaths.headdirFonts, GlobalPaths.headdirTextures }, - new string[] { GlobalPaths.headGameDirFonts, GlobalPaths.headGameDirTextures }); - } - } - - public static AssetCacheDef ItemFaceTexture - { - get - { - return new AssetCacheDef("Decal", - new string[] { "Texture" }, - new string[] { ".png" }, - new string[] { GlobalPaths.facedirTextures }, - new string[] { GlobalPaths.faceGameDirTextures }); - } - } - - public static AssetCacheDef ItemShirtTexture - { - get - { - return new AssetCacheDef("Shirt", - new string[] { "ShirtTemplate" }, - new string[] { ".png" }, - new string[] { GlobalPaths.shirtdirTextures }, - new string[] { GlobalPaths.shirtGameDirTextures }); - } - } - - public static AssetCacheDef ItemTShirtTexture - { - get - { - return new AssetCacheDef("ShirtGraphic", - new string[] { "Graphic" }, - new string[] { ".png" }, - new string[] { GlobalPaths.tshirtdirTextures }, - new string[] { GlobalPaths.tshirtGameDirTextures }); - } - } - - public static AssetCacheDef ItemPantsTexture - { - get - { - return new AssetCacheDef("Pants", - new string[] { "PantsTemplate" }, - new string[] { ".png" }, - new string[] { GlobalPaths.pantsdirTextures }, - new string[] { GlobalPaths.pantsGameDirTextures }); - } - } -} -#endregion - -#region XML Types -public enum XMLTypes -{ - Token, - Bool, - Float, - String, - Vector2Int16, - Int -} -#endregion - -#region Roblox XML Parser -public static class RobloxXML -{ - public static void EditRenderSettings(XDocument doc, string setting, string value, XMLTypes type) - { - var v = from nodes in doc.Descendants("Item") - where nodes.Attribute("class").Value == "RenderSettings" - select nodes; - - foreach (var item in v) - { - var v2 = from nodes in item.Descendants((type != XMLTypes.Vector2Int16 ? type.ToString().ToLower() : "Vector2int16")) - where nodes.Attribute("name").Value == setting - select nodes; - - foreach (var item2 in v2) + get { - if (type != XMLTypes.Vector2Int16) - { - item2.Value = value; - } - else - { - string[] vals = value.Split('x'); - - var v3 = from nodes in item2.Descendants("X") - select nodes; - - foreach (var item3 in v3) - { - item3.Value = vals[0]; - } - - var v4 = from nodes in item2.Descendants("Y") - select nodes; - - foreach (var item4 in v4) - { - item4.Value = vals[1]; - } - } - } - } - } - - public static bool IsRenderSettingStringValid(XDocument doc, string setting, XMLTypes type) - { - if (type != XMLTypes.String) - return false; - - var v = from nodes in doc.Descendants("Item") - where nodes.Attribute("class").Value == "RenderSettings" - select nodes; - - foreach (var item in v) - { - var v2 = from nodes in item.Descendants(type.ToString().ToLower()) - where nodes.Attribute("name").Value == setting - select nodes; - - foreach (var item2 in v2) - { - return true; + return new AssetCacheDef("Sound", + new string[] { "SoundId" }, + new string[] { ".wav" }, + new string[] { GlobalPaths.hatdirSounds }, + new string[] { GlobalPaths.hatGameDirSounds }); } } - return false; - } - - public static string GetRenderSettings(XDocument doc, string setting, XMLTypes type) - { - var v = from nodes in doc.Descendants("Item") - where nodes.Attribute("class").Value == "RenderSettings" - select nodes; - - foreach (var item in v) + public static AssetCacheDef ItemHatScript { - var v2 = from nodes in item.Descendants((type != XMLTypes.Vector2Int16 ? type.ToString().ToLower() : "Vector2int16")) - where nodes.Attribute("name").Value == setting - select nodes; - - foreach (var item2 in v2) + get { - if (type != XMLTypes.Vector2Int16) - { - return item2.Value; - } - else - { - string ValX = ""; - string ValY = ""; - - var v3 = from nodes in item2.Descendants("X") - select nodes; - - foreach (var item3 in v3) - { - ValX = item3.Value; - } - - var v4 = from nodes in item2.Descendants("Y") - select nodes; - - foreach (var item4 in v4) - { - ValY = item4.Value; - } - - return ValX + "x" + ValY; - } + return new AssetCacheDef("Script", + new string[] { "LinkedSource" }, + new string[] { ".lua" }, + new string[] { GlobalPaths.hatdirScripts }, + new string[] { GlobalPaths.hatGameDirScripts }); } } - return ""; - } - - public static string GetURLInNodes(XDocument doc, string itemClassValue, string itemIdValue, string url) - { - var v = from nodes in doc.Descendants("Item") - where nodes.Attribute("class").Value == itemClassValue - select nodes; - - foreach (var item in v) + public static AssetCacheDef ItemHatLocalScript { - var v2 = from nodes in item.Descendants("Content") - where nodes.Attribute("name").Value == itemIdValue - select nodes; - - foreach (var item2 in v2) + get { - var v3 = from nodes in item2.Descendants("url") + return new AssetCacheDef("LocalScript", + new string[] { "LinkedSource" }, + new string[] { ".lua" }, + new string[] { GlobalPaths.hatdirScripts }, + new string[] { GlobalPaths.hatGameDirScripts }); + } + } + + public static AssetCacheDef ItemHeadFonts + { + get + { + return new AssetCacheDef("SpecialMesh", + new string[] { "MeshId", "TextureId" }, + new string[] { ".mesh", ".png" }, + new string[] { GlobalPaths.headdirFonts, GlobalPaths.headdirTextures }, + new string[] { GlobalPaths.headGameDirFonts, GlobalPaths.headGameDirTextures }); + } + } + + public static AssetCacheDef ItemFaceTexture + { + get + { + return new AssetCacheDef("Decal", + new string[] { "Texture" }, + new string[] { ".png" }, + new string[] { GlobalPaths.facedirTextures }, + new string[] { GlobalPaths.faceGameDirTextures }); + } + } + + public static AssetCacheDef ItemShirtTexture + { + get + { + return new AssetCacheDef("Shirt", + new string[] { "ShirtTemplate" }, + new string[] { ".png" }, + new string[] { GlobalPaths.shirtdirTextures }, + new string[] { GlobalPaths.shirtGameDirTextures }); + } + } + + public static AssetCacheDef ItemTShirtTexture + { + get + { + return new AssetCacheDef("ShirtGraphic", + new string[] { "Graphic" }, + new string[] { ".png" }, + new string[] { GlobalPaths.tshirtdirTextures }, + new string[] { GlobalPaths.tshirtGameDirTextures }); + } + } + + public static AssetCacheDef ItemPantsTexture + { + get + { + return new AssetCacheDef("Pants", + new string[] { "PantsTemplate" }, + new string[] { ".png" }, + new string[] { GlobalPaths.pantsdirTextures }, + new string[] { GlobalPaths.pantsGameDirTextures }); + } + } + } + #endregion + + #region XML Types + public enum XMLTypes + { + Token, + Bool, + Float, + String, + Vector2Int16, + Int + } + #endregion + + #region Roblox XML Parser + public static class RobloxXML + { + public static void EditRenderSettings(XDocument doc, string setting, string value, XMLTypes type) + { + var v = from nodes in doc.Descendants("Item") + where nodes.Attribute("class").Value == "RenderSettings" + select nodes; + + foreach (var item in v) + { + var v2 = from nodes in item.Descendants((type != XMLTypes.Vector2Int16 ? type.ToString().ToLower() : "Vector2int16")) + where nodes.Attribute("name").Value == setting select nodes; - foreach (var item3 in v3) + foreach (var item2 in v2) { - if (!item3.Value.Contains("rbxassetid")) + if (type != XMLTypes.Vector2Int16) { - if (!item3.Value.Contains("rbxasset")) + item2.Value = value; + } + else + { + string[] vals = value.Split('x'); + + var v3 = from nodes in item2.Descendants("X") + select nodes; + + foreach (var item3 in v3) + { + item3.Value = vals[0]; + } + + var v4 = from nodes in item2.Descendants("Y") + select nodes; + + foreach (var item4 in v4) + { + item4.Value = vals[1]; + } + } + } + } + } + + public static bool IsRenderSettingStringValid(XDocument doc, string setting, XMLTypes type) + { + if (type != XMLTypes.String) + return false; + + var v = from nodes in doc.Descendants("Item") + where nodes.Attribute("class").Value == "RenderSettings" + select nodes; + + foreach (var item in v) + { + var v2 = from nodes in item.Descendants(type.ToString().ToLower()) + where nodes.Attribute("name").Value == setting + select nodes; + + foreach (var item2 in v2) + { + return true; + } + } + + return false; + } + + public static string GetRenderSettings(XDocument doc, string setting, XMLTypes type) + { + var v = from nodes in doc.Descendants("Item") + where nodes.Attribute("class").Value == "RenderSettings" + select nodes; + + foreach (var item in v) + { + var v2 = from nodes in item.Descendants((type != XMLTypes.Vector2Int16 ? type.ToString().ToLower() : "Vector2int16")) + where nodes.Attribute("name").Value == setting + select nodes; + + foreach (var item2 in v2) + { + if (type != XMLTypes.Vector2Int16) + { + return item2.Value; + } + else + { + string ValX = ""; + string ValY = ""; + + var v3 = from nodes in item2.Descendants("X") + select nodes; + + foreach (var item3 in v3) + { + ValX = item3.Value; + } + + var v4 = from nodes in item2.Descendants("Y") + select nodes; + + foreach (var item4 in v4) + { + ValY = item4.Value; + } + + return ValX + "x" + ValY; + } + } + } + + return ""; + } + + public static string GetURLInNodes(XDocument doc, string itemClassValue, string itemIdValue, string url) + { + var v = from nodes in doc.Descendants("Item") + where nodes.Attribute("class").Value == itemClassValue + select nodes; + + foreach (var item in v) + { + var v2 = from nodes in item.Descendants("Content") + where nodes.Attribute("name").Value == itemIdValue + select nodes; + + foreach (var item2 in v2) + { + var v3 = from nodes in item2.Descendants("url") + select nodes; + + foreach (var item3 in v3) + { + if (!item3.Value.Contains("rbxassetid")) + { + if (!item3.Value.Contains("rbxasset")) + { + string oldurl = item3.Value; + string urlFixed = NovetusFuncs.FixURLString(oldurl, url); + string peram = "id="; + + if (urlFixed.Contains(peram)) + { + return urlFixed; + } + } + } + else { string oldurl = item3.Value; - string urlFixed = NovetusFuncs.FixURLString(oldurl, url); + string rbxassetid = "rbxassetid://"; + string urlFixed = url + oldurl.After(rbxassetid); string peram = "id="; if (urlFixed.Contains(peram)) @@ -641,35 +656,23 @@ public static class RobloxXML } } } - else - { - string oldurl = item3.Value; - string rbxassetid = "rbxassetid://"; - string urlFixed = url + oldurl.After(rbxassetid); - string peram = "id="; - - if (urlFixed.Contains(peram)) - { - return urlFixed; - } - } } } + + return ""; } - return ""; - } + public static string RemoveInvalidXmlChars(string content) + { + return new string(content.Where(ch => XmlConvert.IsXmlChar(ch)).ToArray()); + } - public static string RemoveInvalidXmlChars(string content) - { - return new string(content.Where(ch => XmlConvert.IsXmlChar(ch)).ToArray()); - } - - public static string ReplaceHexadecimalSymbols(string txt) - { - string r = "[\x00-\x08\x0B\x0C\x0E-\x1F]"; - return Regex.Replace(txt, r, "", RegexOptions.Compiled); + public static string ReplaceHexadecimalSymbols(string txt) + { + string r = "[\x00-\x08\x0B\x0C\x0E-\x1F]"; + return Regex.Replace(txt, r, "", RegexOptions.Compiled); + } } + #endregion + #endregion } -#endregion -#endregion diff --git a/Novetus/NovetusCore/StorageAndFunctions/SecurityFuncs.cs b/Novetus/NovetusCore/StorageAndFunctions/SecurityFuncs.cs index 4ac5072..0fe29f2 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/SecurityFuncs.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/SecurityFuncs.cs @@ -14,369 +14,376 @@ using System.Net; using System.Threading.Tasks; #endregion -#region Security Functions -public class SecurityFuncs +namespace Novetus.Core { - [DllImport("user32.dll")] - static extern int SetWindowText(IntPtr hWnd, string text); - - public static string RandomString(int length) + #region Security Functions + public class SecurityFuncs { - CryptoRandom random = new CryptoRandom(); - const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; - return new string(Enumerable.Repeat(chars, length) - .Select(s => s[random.Next(s.Length)]).ToArray()); - } + [DllImport("user32.dll")] + static extern int SetWindowText(IntPtr hWnd, string text); - public static int GenerateRandomNumber() - { - CryptoRandom random = new CryptoRandom(); - int randomID = 0; - int randIDmode = random.Next(0, 8); - int idlimit = 0; - - switch (randIDmode) + public static string RandomString(int length) { - case 0: - idlimit = 9; - break; - case 1: - idlimit = 99; - break; - case 2: - idlimit = 999; - break; - case 3: - idlimit = 9999; - break; - case 4: - idlimit = 99999; - break; - case 5: - idlimit = 999999; - break; - case 6: - idlimit = 9999999; - break; - case 7: - idlimit = 99999999; - break; - case 8: - default: - break; + CryptoRandom random = new CryptoRandom(); + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; + return new string(Enumerable.Repeat(chars, length) + .Select(s => s[random.Next(s.Length)]).ToArray()); } - if (idlimit > 0) + public static int GenerateRandomNumber() { - randomID = random.Next(0, idlimit); - } - else - { - randomID = random.Next(); - } + CryptoRandom random = new CryptoRandom(); + int randomID = 0; + int randIDmode = random.Next(0, 8); + int idlimit = 0; - //2147483647 is max id. - return randomID; - } - - //these 2 methods are for the clientinfo creator. - public static string Base64DecodeNew(string base64EncodedData) - { - return base64EncodedData.Decrypt(); - } - - public static string Base64DecodeOld(string base64EncodedData) - { - var base64EncodedBytes = Convert.FromBase64String(base64EncodedData); - return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); - } - - //this is for everything else - public static string Base64Decode(string base64EncodedData) - { - try - { - string decode = base64EncodedData.Decrypt(); - return decode; - } - catch(Exception) - { - var base64EncodedBytes = Convert.FromBase64String(base64EncodedData); - return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); - } - } - - public static string Base64Encode(string plainText, bool oldVer = false) - { - if (oldVer) - { - var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText); - return System.Convert.ToBase64String(plainTextBytes); - } - else - { - return plainText.Crypt(); - } - } - - public static bool IsBase64String(string s) - { - s = s.Trim(); - return (s.Length % 4 == 0) && Regex.IsMatch(s, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None); - } - - public static long UnixTimeNow() - { - var timeSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)); - return (long)timeSpan.TotalSeconds; - } - - public static bool checkClientMD5(string client) - { - if (!GlobalVars.AdminMode) - { - if (!GlobalVars.SelectedClientInfo.AlreadyHasSecurity) + switch (randIDmode) { - string rbxexe = ""; - string BasePath = GlobalPaths.BasePath + "\\clients\\" + client; - if (GlobalVars.SelectedClientInfo.LegacyMode) - { - rbxexe = BasePath + "\\RobloxApp.exe"; - } - else if (GlobalVars.SelectedClientInfo.SeperateFolders) - { - rbxexe = BasePath + "\\client\\RobloxApp_client.exe"; - } - else if (GlobalVars.SelectedClientInfo.UsesCustomClientEXEName) - { - rbxexe = BasePath + @"\\" + GlobalVars.SelectedClientInfo.CustomClientEXEName; - } - else - { - rbxexe = BasePath + "\\RobloxApp_client.exe"; - } - return CheckMD5(GlobalVars.SelectedClientInfo.ClientMD5, rbxexe); - } - else - { - return true; + case 0: + idlimit = 9; + break; + case 1: + idlimit = 99; + break; + case 2: + idlimit = 999; + break; + case 3: + idlimit = 9999; + break; + case 4: + idlimit = 99999; + break; + case 5: + idlimit = 999999; + break; + case 6: + idlimit = 9999999; + break; + case 7: + idlimit = 99999999; + break; + case 8: + default: + break; } - } - else - { - return true; - } - } - - public static bool checkScriptMD5(string client) - { - if (!GlobalVars.AdminMode) - { - if (!GlobalVars.SelectedClientInfo.AlreadyHasSecurity) + + if (idlimit > 0) { - string rbxscript = GlobalPaths.BasePath + "\\clients\\" + client + "\\content\\scripts\\" + GlobalPaths.ScriptName + ".lua"; - return CheckMD5(GlobalVars.SelectedClientInfo.ScriptMD5, rbxscript); - } else { - return true; + randomID = random.Next(0, idlimit); } - } else { - return true; - } - } - - public static bool CheckMD5(string MD5Hash, string path) - { - if (!File.Exists(path)) - return false; - - using (var md5 = MD5.Create()) - { - using (var stream = File.OpenRead(path)) + else { - byte[] hash = md5.ComputeHash(stream); - string clientMD5 = BitConverter.ToString(hash).Replace("-", ""); - if (clientMD5.Equals(MD5Hash)) + randomID = random.Next(); + } + + //2147483647 is max id. + return randomID; + } + + //these 2 methods are for the clientinfo creator. + public static string Base64DecodeNew(string base64EncodedData) + { + return base64EncodedData.Decrypt(); + } + + public static string Base64DecodeOld(string base64EncodedData) + { + var base64EncodedBytes = Convert.FromBase64String(base64EncodedData); + return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); + } + + //this is for everything else + public static string Base64Decode(string base64EncodedData) + { + try + { + string decode = base64EncodedData.Decrypt(); + return decode; + } + catch (Exception) + { + var base64EncodedBytes = Convert.FromBase64String(base64EncodedData); + return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); + } + } + + public static string Base64Encode(string plainText, bool oldVer = false) + { + if (oldVer) + { + var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText); + return System.Convert.ToBase64String(plainTextBytes); + } + else + { + return plainText.Crypt(); + } + } + + public static bool IsBase64String(string s) + { + s = s.Trim(); + return (s.Length % 4 == 0) && Regex.IsMatch(s, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None); + } + + public static long UnixTimeNow() + { + var timeSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)); + return (long)timeSpan.TotalSeconds; + } + + public static bool checkClientMD5(string client) + { + if (!GlobalVars.AdminMode) + { + if (!GlobalVars.SelectedClientInfo.AlreadyHasSecurity) { - return true; + string rbxexe = ""; + string BasePath = GlobalPaths.BasePath + "\\clients\\" + client; + if (GlobalVars.SelectedClientInfo.LegacyMode) + { + rbxexe = BasePath + "\\RobloxApp.exe"; + } + else if (GlobalVars.SelectedClientInfo.SeperateFolders) + { + rbxexe = BasePath + "\\client\\RobloxApp_client.exe"; + } + else if (GlobalVars.SelectedClientInfo.UsesCustomClientEXEName) + { + rbxexe = BasePath + @"\\" + GlobalVars.SelectedClientInfo.CustomClientEXEName; + } + else + { + rbxexe = BasePath + "\\RobloxApp_client.exe"; + } + return CheckMD5(GlobalVars.SelectedClientInfo.ClientMD5, rbxexe); } else { - return false; + return true; } } - } - } - - public static string GenerateMD5(string filename) - { - using (var md5 = MD5.Create()) - { - using (var stream = new BufferedStream(File.OpenRead(filename), 1200000)) + else { - return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", ""); + return true; } } - } - - public static bool IsElevated - { - get - { - return WindowsIdentity.GetCurrent().Owner.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid); - } - } - - public static string RandomStringTitle() - { - CryptoRandom random = new CryptoRandom(); - return new String(' ', random.Next(20)); - } - public static void RenameWindow(Process exe, ScriptType type, string clientname, string mapname) - { - if (!GlobalVars.SelectedClientInfo.AlreadyHasSecurity) + public static bool checkScriptMD5(string client) { - int time = 500; - BackgroundWorker worker = new BackgroundWorker(); - worker.WorkerSupportsCancellation = true; - worker.DoWork += (obj, e) => WorkerDoWork(exe, type, time, worker, clientname, mapname); - worker.RunWorkerAsync(); - } - } - - private static void WorkerKill(Process exe, ScriptType type, int time, BackgroundWorker worker, string clientname, string mapname) - { - worker.DoWork -= (obj, e) => WorkerDoWork(exe, type, time, worker, clientname, mapname); - worker.CancelAsync(); - worker.Dispose(); - } - - private static void WorkerDoWork(Process exe, ScriptType type, int time, BackgroundWorker worker, string clientname, string mapname) - { - DateTime StartTimeAfterMinute = exe.StartTime.AddMinutes(1); - - if (exe.IsRunning()) - { - while (exe.IsRunning()) + if (!GlobalVars.AdminMode) { - if (exe.MainWindowHandle == null && DateTime.Now > StartTimeAfterMinute) - { - exe.Kill(); - WorkerKill(exe, type, time, worker, clientname, mapname); - break; - } - - switch (type) + if (!GlobalVars.SelectedClientInfo.AlreadyHasSecurity) { - case ScriptType.Client: - SetWindowText(exe.MainWindowHandle, "Novetus " - + GlobalVars.ProgramInformation.Version + " - " - + clientname + " " - + ScriptFuncs.Generator.GetNameForType(type) - + " [" + GlobalVars.CurrentServer.ToString() + "]" - + RandomStringTitle()); - break; - case ScriptType.Server: - case ScriptType.Solo: - SetWindowText(exe.MainWindowHandle, "Novetus " - + GlobalVars.ProgramInformation.Version + " - " - + clientname + " " - + ScriptFuncs.Generator.GetNameForType(type) - + (string.IsNullOrWhiteSpace(mapname) ? " [Place1]" : " [" + mapname + "]") - + RandomStringTitle()); - break; - case ScriptType.Studio: - SetWindowText(exe.MainWindowHandle, "Novetus Studio " - + GlobalVars.ProgramInformation.Version + " - " - + clientname - + (string.IsNullOrWhiteSpace(mapname) ? " [Place1]" : " [" + mapname + "]") - + RandomStringTitle()); - break; - case ScriptType.EasterEgg: - default: - SetWindowText(exe.MainWindowHandle, ScriptFuncs.Generator.GetNameForType(type) - + RandomStringTitle()); - break; + string rbxscript = GlobalPaths.BasePath + "\\clients\\" + client + "\\content\\scripts\\" + GlobalPaths.ScriptName + ".lua"; + return CheckMD5(GlobalVars.SelectedClientInfo.ScriptMD5, rbxscript); + } + else + { + return true; } - - Thread.Sleep(time); } - } - else + else + { + return true; + } + } + + public static bool CheckMD5(string MD5Hash, string path) { - Thread.Sleep(time); - RenameWindow(exe, type, clientname, mapname); - } - } + if (!File.Exists(path)) + return false; - public static string GetExternalIPAddress() - { - string ipAddress; - - try - { - ipAddress = new WebClient().DownloadString("https://ipv4.icanhazip.com/").TrimEnd(); + using (var md5 = MD5.Create()) + { + using (var stream = File.OpenRead(path)) + { + byte[] hash = md5.ComputeHash(stream); + string clientMD5 = BitConverter.ToString(hash).Replace("-", ""); + if (clientMD5.Equals(MD5Hash)) + { + return true; + } + else + { + return false; + } + } + } } + + public static string GenerateMD5(string filename) + { + using (var md5 = MD5.Create()) + { + using (var stream = new BufferedStream(File.OpenRead(filename), 1200000)) + { + return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", ""); + } + } + } + + public static bool IsElevated + { + get + { + return WindowsIdentity.GetCurrent().Owner.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid); + } + } + + public static string RandomStringTitle() + { + CryptoRandom random = new CryptoRandom(); + return new String(' ', random.Next(20)); + } + + public static void RenameWindow(Process exe, ScriptType type, string clientname, string mapname) + { + if (!GlobalVars.SelectedClientInfo.AlreadyHasSecurity) + { + int time = 500; + BackgroundWorker worker = new BackgroundWorker(); + worker.WorkerSupportsCancellation = true; + worker.DoWork += (obj, e) => WorkerDoWork(exe, type, time, worker, clientname, mapname); + worker.RunWorkerAsync(); + } + } + + private static void WorkerKill(Process exe, ScriptType type, int time, BackgroundWorker worker, string clientname, string mapname) + { + worker.DoWork -= (obj, e) => WorkerDoWork(exe, type, time, worker, clientname, mapname); + worker.CancelAsync(); + worker.Dispose(); + } + + private static void WorkerDoWork(Process exe, ScriptType type, int time, BackgroundWorker worker, string clientname, string mapname) + { + DateTime StartTimeAfterMinute = exe.StartTime.AddMinutes(1); + + if (exe.IsRunning()) + { + while (exe.IsRunning()) + { + if (exe.MainWindowHandle == null && DateTime.Now > StartTimeAfterMinute) + { + exe.Kill(); + WorkerKill(exe, type, time, worker, clientname, mapname); + break; + } + + switch (type) + { + case ScriptType.Client: + SetWindowText(exe.MainWindowHandle, "Novetus " + + GlobalVars.ProgramInformation.Version + " - " + + clientname + " " + + ScriptFuncs.Generator.GetNameForType(type) + + " [" + GlobalVars.CurrentServer.ToString() + "]" + + RandomStringTitle()); + break; + case ScriptType.Server: + case ScriptType.Solo: + SetWindowText(exe.MainWindowHandle, "Novetus " + + GlobalVars.ProgramInformation.Version + " - " + + clientname + " " + + ScriptFuncs.Generator.GetNameForType(type) + + (string.IsNullOrWhiteSpace(mapname) ? " [Place1]" : " [" + mapname + "]") + + RandomStringTitle()); + break; + case ScriptType.Studio: + SetWindowText(exe.MainWindowHandle, "Novetus Studio " + + GlobalVars.ProgramInformation.Version + " - " + + clientname + + (string.IsNullOrWhiteSpace(mapname) ? " [Place1]" : " [" + mapname + "]") + + RandomStringTitle()); + break; + case ScriptType.EasterEgg: + default: + SetWindowText(exe.MainWindowHandle, ScriptFuncs.Generator.GetNameForType(type) + + RandomStringTitle()); + break; + } + + Thread.Sleep(time); + } + } + else + { + Thread.Sleep(time); + RenameWindow(exe, type, clientname, mapname); + } + } + + public static string GetExternalIPAddress() + { + string ipAddress; + + try + { + ipAddress = new WebClient().DownloadString("https://ipv4.icanhazip.com/").TrimEnd(); + } #if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); + catch (Exception ex) + { + Util.LogExceptions(ex); #else catch (Exception) { #endif - ipAddress = "localhost"; - } + ipAddress = "localhost"; + } - return ipAddress; - } + return ipAddress; + } - //modified from https://stackoverflow.com/questions/14687658/random-name-generator-in-c-sharp - public static string GenerateName(int len) - { - CryptoRandom r = new CryptoRandom(); - string[] consonants = { "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "l", "n", "p", "q", "r", "s", "sh", "zh", "t", "v", "w", "x" }; - string[] vowels = { "a", "e", "i", "o", "u", "ae", "y" }; - string Name = ""; - Name += consonants[r.Next(consonants.Length)].ToUpper(); - Name += vowels[r.Next(vowels.Length)]; - int b = 2; //b tells how many times a new letter has been added. It's 2 right now because the first two letters are already in the name. - while (b < len) + //modified from https://stackoverflow.com/questions/14687658/random-name-generator-in-c-sharp + public static string GenerateName(int len) { - Name += consonants[r.Next(consonants.Length)]; - b++; + CryptoRandom r = new CryptoRandom(); + string[] consonants = { "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "l", "n", "p", "q", "r", "s", "sh", "zh", "t", "v", "w", "x" }; + string[] vowels = { "a", "e", "i", "o", "u", "ae", "y" }; + string Name = ""; + Name += consonants[r.Next(consonants.Length)].ToUpper(); Name += vowels[r.Next(vowels.Length)]; - b++; + int b = 2; //b tells how many times a new letter has been added. It's 2 right now because the first two letters are already in the name. + while (b < len) + { + Name += consonants[r.Next(consonants.Length)]; + b++; + Name += vowels[r.Next(vowels.Length)]; + b++; + } + + return Name; } - return Name; - } - - //https://www.c-sharpcorner.com/article/caesar-cipher-in-c-sharp/ - public static char cipher(char ch, int key) - { - if (!char.IsLetter(ch)) + //https://www.c-sharpcorner.com/article/caesar-cipher-in-c-sharp/ + public static char cipher(char ch, int key) { - return ch; + if (!char.IsLetter(ch)) + { + return ch; + } + + char d = char.IsUpper(ch) ? 'A' : 'a'; + return (char)((((ch + key) - d) % 26) + d); } - char d = char.IsUpper(ch) ? 'A' : 'a'; - return (char)((((ch + key) - d) % 26) + d); + public static string Encipher(string input, int key) + { + string output = string.Empty; + + foreach (char ch in input) + output += cipher(ch, key); + + return output; + } + + public static string Decipher(string input, int key) + { + return Encipher(input, 26 - key); + } } - - public static string Encipher(string input, int key) - { - string output = string.Empty; - - foreach (char ch in input) - output += cipher(ch, key); - - return output; - } - - public static string Decipher(string input, int key) - { - return Encipher(input, 26 - key); - } -} -#endregion \ No newline at end of file + #endregion +} \ No newline at end of file diff --git a/Novetus/NovetusCore/StorageAndFunctions/Util.cs b/Novetus/NovetusCore/StorageAndFunctions/Util.cs index 73bb7cf..e0237d7 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/Util.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/Util.cs @@ -20,342 +20,306 @@ using Mono.Nat; #endif #endregion -#region Utils - -public static class Util +namespace Novetus.Core { - #region Extensions - //This code was brought to you by: - //https://stackoverflow.com/questions/1926264/color-different-parts-of-a-richtextbox-string - //https://stackoverflow.com/questions/262280/how-can-i-know-if-a-process-is-running - //https://stackoverflow.com/questions/444798/case-insensitive-containsstring - //https://stackoverflow.com/questions/6084940/how-do-i-search-a-multi-dimensional-array - //https://www.dotnetperls.com/between-before-after - //https://stackoverflow.com/questions/12422619/can-i-disable-the-close-button-of-a-form-using-c - //https://stackoverflow.com/questions/9031537/really-simple-encryption-with-c-sharp-and-symmetricalgorithm + #region Utils - #region Rich Text Box Extensions - public static void AppendText(this RichTextBox box, string text, Color color) + public static class Util { - box.SelectionStart = box.TextLength; - box.SelectionLength = 0; + #region Extensions + //This code was brought to you by: + //https://stackoverflow.com/questions/1926264/color-different-parts-of-a-richtextbox-string + //https://stackoverflow.com/questions/262280/how-can-i-know-if-a-process-is-running + //https://stackoverflow.com/questions/444798/case-insensitive-containsstring + //https://stackoverflow.com/questions/6084940/how-do-i-search-a-multi-dimensional-array + //https://www.dotnetperls.com/between-before-after + //https://stackoverflow.com/questions/12422619/can-i-disable-the-close-button-of-a-form-using-c + //https://stackoverflow.com/questions/9031537/really-simple-encryption-with-c-sharp-and-symmetricalgorithm - box.SelectionColor = color; - box.AppendText(text); - box.SelectionColor = box.ForeColor; - } - #endregion - - #region Process Extensions - public static bool IsRunning(this Process process) - { - try + #region Rich Text Box Extensions + public static void AppendText(this RichTextBox box, string text, Color color) { - Process.GetProcessById(process.Id); + box.SelectionStart = box.TextLength; + box.SelectionLength = 0; + + box.SelectionColor = color; + box.AppendText(text); + box.SelectionColor = box.ForeColor; } - catch (InvalidOperationException) + #endregion + + #region Process Extensions + public static bool IsRunning(this Process process) { - return false; - } - catch (ArgumentException) - { - return false; - } - return true; - } - #endregion - - #region String Extensions - public static bool Contains(this string source, string toCheck, StringComparison comp) - { - if (source == null) - return false; - return source.IndexOf(toCheck, comp) >= 0; - } - #endregion - - #region Substring Extensions - /// - /// Get string value between [first] a and [last] b. - /// - public static string Between(this string value, string a, string b) - { - int posA = value.IndexOf(a); - int posB = value.LastIndexOf(b); - if (posA == -1) - { - return ""; - } - if (posB == -1) - { - return ""; - } - int adjustedPosA = posA + a.Length; - if (adjustedPosA >= posB) - { - return ""; - } - return value.Substring(adjustedPosA, posB - adjustedPosA); - } - - /// - /// Get string value after [first] a. - /// - public static string Before(this string value, string a) - { - int posA = value.IndexOf(a); - if (posA == -1) - { - return ""; - } - return value.Substring(0, posA); - } - - /// - /// Get string value after [last] a. - /// - public static string After(this string value, string a) - { - int posA = value.LastIndexOf(a); - if (posA == -1) - { - return ""; - } - int adjustedPosA = posA + a.Length; - if (adjustedPosA >= value.Length) - { - return ""; - } - return value.Substring(adjustedPosA); - } - #endregion - - #region String Utilities - private static byte[] key = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 }; - private static byte[] iv = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 }; - - public static string Crypt(this string text) - { - SymmetricAlgorithm algorithm = DES.Create(); - ICryptoTransform transform = algorithm.CreateEncryptor(key, iv); - byte[] inputbuffer = Encoding.Unicode.GetBytes(text); - byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length); - return Convert.ToBase64String(outputBuffer); - } - - public static string Decrypt(this string text) - { - SymmetricAlgorithm algorithm = DES.Create(); - ICryptoTransform transform = algorithm.CreateDecryptor(key, iv); - byte[] inputbuffer = Convert.FromBase64String(text); - byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length); - return Encoding.Unicode.GetString(outputBuffer); - } - #endregion - - #region Exception Helpers - //https://github.com/AlexMelw/EasySharp/blob/master/NHelpers/ExceptionsDealing/Extensions/ExceptionExtensions.cs - /// - /// Gets the entire stack trace consisting of exception's footprints (File, Method, LineNumber) - /// - /// Source - /// - /// that represents the entire stack trace consisting of exception's footprints (File, - /// Method, LineNumber) - /// - public static string GetExceptionFootprints(this Exception exception) - { - StackTrace stackTrace = new StackTrace(exception, true); - StackFrame[] frames = stackTrace.GetFrames(); - - if (ReferenceEquals(frames, null)) - { - return string.Empty; - } - - var traceStringBuilder = new StringBuilder(); - - for (var i = 0; i < frames.Length; i++) - { - StackFrame frame = frames[i]; - - if (frame.GetFileLineNumber() < 1) - continue; - - traceStringBuilder.AppendLine($"File: {frame.GetFileName()}"); - traceStringBuilder.AppendLine($"Method: {frame.GetMethod().Name}"); - traceStringBuilder.AppendLine($"LineNumber: {frame.GetFileLineNumber()}"); - - if (i == frames.Length - 1) - break; - - traceStringBuilder.AppendLine(" ---> "); - } - - string stackTraceFootprints = traceStringBuilder.ToString(); - - if (string.IsNullOrWhiteSpace(stackTraceFootprints)) - return "NO DETECTED FOOTPRINTS"; - - return stackTraceFootprints; - } - #endregion - - #region DirectoryInfo Extensions - public static IEnumerable GetFilesByExtensions(this DirectoryInfo dir, params string[] extensions) - { - if (extensions == null) - throw new ArgumentNullException("extensions"); - IEnumerable files = dir.EnumerateFiles(); - return files.Where(f => extensions.Contains(f.Extension)); - } - #endregion - - #region DateTime Extensions - //https://stackoverflow.com/questions/5672862/check-if-datetime-instance-falls-in-between-other-two-datetime-objects - public static bool IsBetweenTwoDates(this DateTime dt, DateTime start, DateTime end) - { - return dt >= start && dt <= end; - } - #endregion - - #region Form Extensions - [DllImport("user32")] - public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); - - [DllImport("user32")] - public static extern bool EnableMenuItem(IntPtr hMenu, uint itemId, uint uEnable); - - public static void DisableCloseButton(this Form form) - { - // The 1 parameter means to gray out. 0xF060 is SC_CLOSE. - EnableMenuItem(GetSystemMenu(form.Handle, false), 0xF060, 1); - } - - public static void EnableCloseButton(this Form form) - { - // The zero parameter means to enable. 0xF060 is SC_CLOSE. - EnableMenuItem(GetSystemMenu(form.Handle, false), 0xF060, 0); - } - #endregion - - #region Process Extensions - //https://stackoverflow.com/questions/2633628/can-i-get-command-line-arguments-of-other-processes-from-net-c - // Define an extension method for type System.Process that returns the command - // line via WMI. - public static string GetCommandLine(this Process process) - { - string cmdLine = null; - using (var searcher = new ManagementObjectSearcher( - $"SELECT CommandLine FROM Win32_Process WHERE ProcessId = {process.Id}")) - { - // By definition, the query returns at most 1 match, because the process - // is looked up by ID (which is unique by definition). - using (var matchEnum = searcher.Get().GetEnumerator()) + try { - if (matchEnum.MoveNext()) // Move to the 1st item. - { - cmdLine = matchEnum.Current["CommandLine"]?.ToString(); - } + Process.GetProcessById(process.Id); } - } - if (cmdLine == null) - { - // Not having found a command line implies 1 of 2 exceptions, which the - // WMI query masked: - // An "Access denied" exception due to lack of privileges. - // A "Cannot process request because the process () has exited." - // exception due to the process having terminated. - // We provoke the same exception again simply by accessing process.MainModule. - var dummy = process.MainModule; // Provoke exception. - } - return cmdLine; - } - - // based off the above function - public static string GetFilePath(this Process process) - { - string path = null; - using (var searcher = new ManagementObjectSearcher( - $"SELECT ExecutablePath FROM Win32_Process WHERE ProcessId = {process.Id}")) - { - // By definition, the query returns at most 1 match, because the process - // is looked up by ID (which is unique by definition). - using (var matchEnum = searcher.Get().GetEnumerator()) + catch (InvalidOperationException) { - if (matchEnum.MoveNext()) // Move to the 1st item. - { - path = matchEnum.Current["ExecutablePath"]?.ToString(); - } + return false; } - } - if (path == null) - { - // Not having found a command line implies 1 of 2 exceptions, which the - // WMI query masked: - // An "Access denied" exception due to lack of privileges. - // A "Cannot process request because the process () has exited." - // exception due to the process having terminated. - // We provoke the same exception again simply by accessing process.MainModule. - var dummy = process.MainModule; // Provoke exception. - } - return path; - } - #endregion - #endregion - - #region Utility Functions - private static DialogResult ShowOverrideWarning(string dest) - { - DialogResult box = MessageBox.Show("A file with a similar name was detected in the directory as '" + dest + - "'.\n\nWould you like to override it?", "Novetus - Override Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); - - return box; - } - - public static void FixedFileCopy(string src, string dest, bool overwrite, bool overwritewarning = false) - { - if (File.Exists(dest)) - { - if (overwrite && overwritewarning) + catch (ArgumentException) { - if (ShowOverrideWarning(dest) == DialogResult.No) - { - return; - } + return false; + } + return true; + } + #endregion + + #region String Extensions + public static bool Contains(this string source, string toCheck, StringComparison comp) + { + if (source == null) + return false; + return source.IndexOf(toCheck, comp) >= 0; + } + #endregion + + #region Substring Extensions + /// + /// Get string value between [first] a and [last] b. + /// + public static string Between(this string value, string a, string b) + { + int posA = value.IndexOf(a); + int posB = value.LastIndexOf(b); + if (posA == -1) + { + return ""; + } + if (posB == -1) + { + return ""; + } + int adjustedPosA = posA + a.Length; + if (adjustedPosA >= posB) + { + return ""; + } + return value.Substring(adjustedPosA, posB - adjustedPosA); + } + + /// + /// Get string value after [first] a. + /// + public static string Before(this string value, string a) + { + int posA = value.IndexOf(a); + if (posA == -1) + { + return ""; + } + return value.Substring(0, posA); + } + + /// + /// Get string value after [last] a. + /// + public static string After(this string value, string a) + { + int posA = value.LastIndexOf(a); + if (posA == -1) + { + return ""; + } + int adjustedPosA = posA + a.Length; + if (adjustedPosA >= value.Length) + { + return ""; + } + return value.Substring(adjustedPosA); + } + #endregion + + #region String Utilities + private static byte[] key = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 }; + private static byte[] iv = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 }; + + public static string Crypt(this string text) + { + SymmetricAlgorithm algorithm = DES.Create(); + ICryptoTransform transform = algorithm.CreateEncryptor(key, iv); + byte[] inputbuffer = Encoding.Unicode.GetBytes(text); + byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length); + return Convert.ToBase64String(outputBuffer); + } + + public static string Decrypt(this string text) + { + SymmetricAlgorithm algorithm = DES.Create(); + ICryptoTransform transform = algorithm.CreateDecryptor(key, iv); + byte[] inputbuffer = Convert.FromBase64String(text); + byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length); + return Encoding.Unicode.GetString(outputBuffer); + } + #endregion + + #region Exception Helpers + //https://github.com/AlexMelw/EasySharp/blob/master/NHelpers/ExceptionsDealing/Extensions/ExceptionExtensions.cs + /// + /// Gets the entire stack trace consisting of exception's footprints (File, Method, LineNumber) + /// + /// Source + /// + /// that represents the entire stack trace consisting of exception's footprints (File, + /// Method, LineNumber) + /// + public static string GetExceptionFootprints(this Exception exception) + { + StackTrace stackTrace = new StackTrace(exception, true); + StackFrame[] frames = stackTrace.GetFrames(); + + if (ReferenceEquals(frames, null)) + { + return string.Empty; } - File.SetAttributes(dest, FileAttributes.Normal); - } + var traceStringBuilder = new StringBuilder(); - File.Copy(src, dest, overwrite); - File.SetAttributes(dest, FileAttributes.Normal); - } - - public static void FixedFileDelete(string src) - { - if (File.Exists(src)) - { - File.SetAttributes(src, FileAttributes.Normal); - File.Delete(src); - } - } - - public static void FixedFileMove(string src, string dest, bool overwrite, bool overwritewarning = false) - { - if (src.Equals(dest)) - return; - - if (!File.Exists(dest)) - { - File.SetAttributes(src, FileAttributes.Normal); - File.Move(src, dest); - } - else - { - if (overwrite) + for (var i = 0; i < frames.Length; i++) { - if (overwritewarning) + StackFrame frame = frames[i]; + + if (frame.GetFileLineNumber() < 1) + continue; + + traceStringBuilder.AppendLine($"File: {frame.GetFileName()}"); + traceStringBuilder.AppendLine($"Method: {frame.GetMethod().Name}"); + traceStringBuilder.AppendLine($"LineNumber: {frame.GetFileLineNumber()}"); + + if (i == frames.Length - 1) + break; + + traceStringBuilder.AppendLine(" ---> "); + } + + string stackTraceFootprints = traceStringBuilder.ToString(); + + if (string.IsNullOrWhiteSpace(stackTraceFootprints)) + return "NO DETECTED FOOTPRINTS"; + + return stackTraceFootprints; + } + #endregion + + #region DirectoryInfo Extensions + public static IEnumerable GetFilesByExtensions(this DirectoryInfo dir, params string[] extensions) + { + if (extensions == null) + throw new ArgumentNullException("extensions"); + IEnumerable files = dir.EnumerateFiles(); + return files.Where(f => extensions.Contains(f.Extension)); + } + #endregion + + #region DateTime Extensions + //https://stackoverflow.com/questions/5672862/check-if-datetime-instance-falls-in-between-other-two-datetime-objects + public static bool IsBetweenTwoDates(this DateTime dt, DateTime start, DateTime end) + { + return dt >= start && dt <= end; + } + #endregion + + #region Form Extensions + [DllImport("user32")] + public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); + + [DllImport("user32")] + public static extern bool EnableMenuItem(IntPtr hMenu, uint itemId, uint uEnable); + + public static void DisableCloseButton(this Form form) + { + // The 1 parameter means to gray out. 0xF060 is SC_CLOSE. + EnableMenuItem(GetSystemMenu(form.Handle, false), 0xF060, 1); + } + + public static void EnableCloseButton(this Form form) + { + // The zero parameter means to enable. 0xF060 is SC_CLOSE. + EnableMenuItem(GetSystemMenu(form.Handle, false), 0xF060, 0); + } + #endregion + + #region Process Extensions + //https://stackoverflow.com/questions/2633628/can-i-get-command-line-arguments-of-other-processes-from-net-c + // Define an extension method for type System.Process that returns the command + // line via WMI. + public static string GetCommandLine(this Process process) + { + string cmdLine = null; + using (var searcher = new ManagementObjectSearcher( + $"SELECT CommandLine FROM Win32_Process WHERE ProcessId = {process.Id}")) + { + // By definition, the query returns at most 1 match, because the process + // is looked up by ID (which is unique by definition). + using (var matchEnum = searcher.Get().GetEnumerator()) + { + if (matchEnum.MoveNext()) // Move to the 1st item. + { + cmdLine = matchEnum.Current["CommandLine"]?.ToString(); + } + } + } + if (cmdLine == null) + { + // Not having found a command line implies 1 of 2 exceptions, which the + // WMI query masked: + // An "Access denied" exception due to lack of privileges. + // A "Cannot process request because the process () has exited." + // exception due to the process having terminated. + // We provoke the same exception again simply by accessing process.MainModule. + var dummy = process.MainModule; // Provoke exception. + } + return cmdLine; + } + + // based off the above function + public static string GetFilePath(this Process process) + { + string path = null; + using (var searcher = new ManagementObjectSearcher( + $"SELECT ExecutablePath FROM Win32_Process WHERE ProcessId = {process.Id}")) + { + // By definition, the query returns at most 1 match, because the process + // is looked up by ID (which is unique by definition). + using (var matchEnum = searcher.Get().GetEnumerator()) + { + if (matchEnum.MoveNext()) // Move to the 1st item. + { + path = matchEnum.Current["ExecutablePath"]?.ToString(); + } + } + } + if (path == null) + { + // Not having found a command line implies 1 of 2 exceptions, which the + // WMI query masked: + // An "Access denied" exception due to lack of privileges. + // A "Cannot process request because the process () has exited." + // exception due to the process having terminated. + // We provoke the same exception again simply by accessing process.MainModule. + var dummy = process.MainModule; // Provoke exception. + } + return path; + } + #endregion + #endregion + + #region Utility Functions + private static DialogResult ShowOverrideWarning(string dest) + { + DialogResult box = MessageBox.Show("A file with a similar name was detected in the directory as '" + dest + + "'.\n\nWould you like to override it?", "Novetus - Override Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); + + return box; + } + + public static void FixedFileCopy(string src, string dest, bool overwrite, bool overwritewarning = false) + { + if (File.Exists(dest)) + { + if (overwrite && overwritewarning) { if (ShowOverrideWarning(dest) == DialogResult.No) { @@ -363,467 +327,505 @@ public static class Util } } - FixedFileDelete(dest); + File.SetAttributes(dest, FileAttributes.Normal); + } + + File.Copy(src, dest, overwrite); + File.SetAttributes(dest, FileAttributes.Normal); + } + + public static void FixedFileDelete(string src) + { + if (File.Exists(src)) + { + File.SetAttributes(src, FileAttributes.Normal); + File.Delete(src); + } + } + + public static void FixedFileMove(string src, string dest, bool overwrite, bool overwritewarning = false) + { + if (src.Equals(dest)) + return; + + if (!File.Exists(dest)) + { File.SetAttributes(src, FileAttributes.Normal); File.Move(src, dest); } else { - throw new IOException("Cannot create a file when that file already exists. FixedFileMove cannot override files with overwrite disabled."); + if (overwrite) + { + if (overwritewarning) + { + if (ShowOverrideWarning(dest) == DialogResult.No) + { + return; + } + } + + FixedFileDelete(dest); + File.SetAttributes(src, FileAttributes.Normal); + File.Move(src, dest); + } + else + { + throw new IOException("Cannot create a file when that file already exists. FixedFileMove cannot override files with overwrite disabled."); + } } } - } - //modified from the following: - //https://stackoverflow.com/questions/28887314/performance-of-image-loading - //https://stackoverflow.com/questions/2479771/c-why-am-i-getting-the-process-cannot-access-the-file-because-it-is-being-u - public static Image LoadImage(string fileFullName, string fallbackFileFullName = "") - { - if (string.IsNullOrWhiteSpace(fileFullName)) - return null; - - Image image = null; - - try + //modified from the following: + //https://stackoverflow.com/questions/28887314/performance-of-image-loading + //https://stackoverflow.com/questions/2479771/c-why-am-i-getting-the-process-cannot-access-the-file-because-it-is-being-u + public static Image LoadImage(string fileFullName, string fallbackFileFullName = "") { - using (MemoryStream ms = new MemoryStream(File.ReadAllBytes(fileFullName))) - { - image = Image.FromStream(ms); - } + if (string.IsNullOrWhiteSpace(fileFullName)) + return null; - // PropertyItems seem to get lost when fileStream is closed to quickly (?); perhaps - // this is the reason Microsoft didn't want to close it in the first place. - PropertyItem[] items = image.PropertyItems; - - foreach (PropertyItem item in items) - { - image.SetPropertyItem(item); - } - } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - LogExceptions(ex); -#else - catch (Exception) - { -#endif - if (!string.IsNullOrWhiteSpace(fallbackFileFullName)) - image = LoadImage(fallbackFileFullName); - } - - return image; - } - - //https://social.msdn.microsoft.com/Forums/vstudio/en-US/b0c31115-f6f0-4de5-a62d-d766a855d4d1/directorygetfiles-with-searchpattern-to-get-all-dll-and-exe-files-in-one-call?forum=netfxbcl - public static string[] GetFiles(string path, string searchPattern, SearchOption searchOption) - { - string[] searchPatterns = searchPattern.Split('|'); - List files = new List(); - foreach (string sp in searchPatterns) - files.AddRange(System.IO.Directory.GetFiles(path, sp, searchOption)); - files.Sort(); - return files.ToArray(); - } - - // Credit to Carrot for the original code. Rewote it to be smaller. - public static string CryptStringWithByte(string word) - { - byte[] bytes = Encoding.ASCII.GetBytes(word); - string result = ""; - for (int i = 0; i < bytes.Length; i++) { result += Convert.ToChar(0x55 ^ bytes[i]); } - return result; - } - - //https://stackoverflow.com/questions/1879395/how-do-i-generate-a-stream-from-a-string - public static Stream GenerateStreamFromString(string s) - { - var stream = new MemoryStream(); - var writer = new StreamWriter(stream); - writer.Write(s); - writer.Flush(); - stream.Position = 0; - return stream; - } - - //https://stackoverflow.com/questions/14488796/does-net-provide-an-easy-way-convert-bytes-to-kb-mb-gb-etc - private static readonly string[] SizeSuffixes = - { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; - public static string SizeSuffix(Int64 value, int decimalPlaces = 1) - { - if (decimalPlaces < 0) { throw new ArgumentOutOfRangeException("decimalPlaces"); } - if (value < 0) { return "-" + SizeSuffix(-value, decimalPlaces); } - if (value == 0) { return string.Format("{0:n" + decimalPlaces + "} bytes", 0); } - - // mag is 0 for bytes, 1 for KB, 2, for MB, etc. - int mag = (int)Math.Log(value, 1024); - - // 1L << (mag * 10) == 2 ^ (10 * mag) - // [i.e. the number of bytes in the unit corresponding to mag] - decimal adjustedSize = (decimal)value / (1L << (mag * 10)); - - // make adjustment when the value is large enough that - // it would round up to 1000 or more - if (Math.Round(adjustedSize, decimalPlaces) >= 1000) - { - mag += 1; - adjustedSize /= 1024; - } - - return string.Format("{0:n" + decimalPlaces + "} {1}", - adjustedSize, - SizeSuffixes[mag]); - } - - //https://stackoverflow.com/questions/11927116/getting-files-recursively-skip-files-directories-that-cannot-be-read - public static string[] FindAllFiles(string rootDir) - { - var pathsToSearch = new Queue(); - var foundFiles = new List(); - - pathsToSearch.Enqueue(rootDir); - - while (pathsToSearch.Count > 0) - { - var dir = pathsToSearch.Dequeue(); + Image image = null; try { - var files = Directory.GetFiles(dir); - foreach (var file in Directory.GetFiles(dir)) + using (MemoryStream ms = new MemoryStream(File.ReadAllBytes(fileFullName))) { - foundFiles.Add(file); + image = Image.FromStream(ms); } - foreach (var subDir in Directory.GetDirectories(dir)) - { - pathsToSearch.Enqueue(subDir); - } + // PropertyItems seem to get lost when fileStream is closed to quickly (?); perhaps + // this is the reason Microsoft didn't want to close it in the first place. + PropertyItem[] items = image.PropertyItems; + foreach (PropertyItem item in items) + { + image.SetPropertyItem(item); + } } #if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { LogExceptions(ex); +#else + catch (Exception) + { +#endif + if (!string.IsNullOrWhiteSpace(fallbackFileFullName)) + image = LoadImage(fallbackFileFullName); + } + + return image; + } + + //https://social.msdn.microsoft.com/Forums/vstudio/en-US/b0c31115-f6f0-4de5-a62d-d766a855d4d1/directorygetfiles-with-searchpattern-to-get-all-dll-and-exe-files-in-one-call?forum=netfxbcl + public static string[] GetFiles(string path, string searchPattern, SearchOption searchOption) + { + string[] searchPatterns = searchPattern.Split('|'); + List files = new List(); + foreach (string sp in searchPatterns) + files.AddRange(System.IO.Directory.GetFiles(path, sp, searchOption)); + files.Sort(); + return files.ToArray(); + } + + // Credit to Carrot for the original code. Rewote it to be smaller. + public static string CryptStringWithByte(string word) + { + byte[] bytes = Encoding.ASCII.GetBytes(word); + string result = ""; + for (int i = 0; i < bytes.Length; i++) { result += Convert.ToChar(0x55 ^ bytes[i]); } + return result; + } + + //https://stackoverflow.com/questions/1879395/how-do-i-generate-a-stream-from-a-string + public static Stream GenerateStreamFromString(string s) + { + var stream = new MemoryStream(); + var writer = new StreamWriter(stream); + writer.Write(s); + writer.Flush(); + stream.Position = 0; + return stream; + } + + //https://stackoverflow.com/questions/14488796/does-net-provide-an-easy-way-convert-bytes-to-kb-mb-gb-etc + private static readonly string[] SizeSuffixes = + { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; + public static string SizeSuffix(Int64 value, int decimalPlaces = 1) + { + if (decimalPlaces < 0) { throw new ArgumentOutOfRangeException("decimalPlaces"); } + if (value < 0) { return "-" + SizeSuffix(-value, decimalPlaces); } + if (value == 0) { return string.Format("{0:n" + decimalPlaces + "} bytes", 0); } + + // mag is 0 for bytes, 1 for KB, 2, for MB, etc. + int mag = (int)Math.Log(value, 1024); + + // 1L << (mag * 10) == 2 ^ (10 * mag) + // [i.e. the number of bytes in the unit corresponding to mag] + decimal adjustedSize = (decimal)value / (1L << (mag * 10)); + + // make adjustment when the value is large enough that + // it would round up to 1000 or more + if (Math.Round(adjustedSize, decimalPlaces) >= 1000) + { + mag += 1; + adjustedSize /= 1024; + } + + return string.Format("{0:n" + decimalPlaces + "} {1}", + adjustedSize, + SizeSuffixes[mag]); + } + + //https://stackoverflow.com/questions/11927116/getting-files-recursively-skip-files-directories-that-cannot-be-read + public static string[] FindAllFiles(string rootDir) + { + var pathsToSearch = new Queue(); + var foundFiles = new List(); + + pathsToSearch.Enqueue(rootDir); + + while (pathsToSearch.Count > 0) + { + var dir = pathsToSearch.Dequeue(); + + try + { + var files = Directory.GetFiles(dir); + foreach (var file in Directory.GetFiles(dir)) + { + foundFiles.Add(file); + } + + foreach (var subDir in Directory.GetDirectories(dir)) + { + pathsToSearch.Enqueue(subDir); + } + + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + LogExceptions(ex); #else catch (Exception) { #endif + } } + + return foundFiles.ToArray(); } - return foundFiles.ToArray(); - } + //https://stackoverflow.com/questions/66667263/i-want-to-remove-special-characters-from-file-name-without-affecting-extension-i + //https://stackoverflow.com/questions/3218910/rename-a-file-in-c-sharp - //https://stackoverflow.com/questions/66667263/i-want-to-remove-special-characters-from-file-name-without-affecting-extension-i - //https://stackoverflow.com/questions/3218910/rename-a-file-in-c-sharp - - public static bool FileHasInvalidChars(string path) - { - string fileName = Path.GetFileName(path); - - if (Regex.Match(fileName, @"[^\w-.'_!()& ]") != Match.Empty) + public static bool FileHasInvalidChars(string path) { - return true; - } - - return false; - } - - public static void RenameFileWithInvalidChars(string path) - { - try - { - if (!FileHasInvalidChars(path)) - return; - - string pathWithoutFilename = Path.GetDirectoryName(path); string fileName = Path.GetFileName(path); - fileName = Regex.Replace(fileName, @"[^\w-.'_!()& ]", ""); - string finalPath = pathWithoutFilename + "\\" + fileName; - FixedFileMove(path, finalPath, File.Exists(finalPath)); + if (Regex.Match(fileName, @"[^\w-.'_!()& ]") != Match.Empty) + { + return true; + } + + return false; } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) + + public static void RenameFileWithInvalidChars(string path) { - LogExceptions(ex); + try + { + if (!FileHasInvalidChars(path)) + return; + + string pathWithoutFilename = Path.GetDirectoryName(path); + string fileName = Path.GetFileName(path); + fileName = Regex.Replace(fileName, @"[^\w-.'_!()& ]", ""); + string finalPath = pathWithoutFilename + "\\" + fileName; + + FixedFileMove(path, finalPath, File.Exists(finalPath)); + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + LogExceptions(ex); #else catch (Exception) { #endif + } } - } - //http://stevenhollidge.blogspot.com/2012/06/async-taskdelay.html - public static Task Delay(int milliseconds) - { + //http://stevenhollidge.blogspot.com/2012/06/async-taskdelay.html + public static Task Delay(int milliseconds) + { #if NET4 var tcs = new TaskCompletionSource(); new System.Threading.Timer(_ => tcs.SetResult(null)).Change(milliseconds, -1); return tcs.Task; #elif NET481 - return Task.Delay(milliseconds); + return Task.Delay(milliseconds); #endif - } - - public static void LogPrint(string text, int type = 1) - { - Logger log = LogManager.GetCurrentClassLogger(); - - switch (type) - { - case 2: - log.Error(text); - break; - case 3: - log.Warn(text); - break; - default: - log.Info(text); - break; - } - } - -#if LAUNCHER || URI || BASICLAUNCHER - public static void LogExceptions(Exception ex) - { - string message = (ex.Message != null ? ex.Message.ToString() : "N/A"); - - ConsolePrint(ex.Source + " Exception: " + message, 2, false, true); - - LogPrint("EXCEPTION|MESSAGE: " + message, 2); - LogPrint("EXCEPTION|STACK TRACE: " + (!string.IsNullOrWhiteSpace(ex.StackTrace) ? ex.StackTrace : "N/A"), 2); - LogPrint("EXCEPTION|ADDITIONAL INFO: " + (ex != null ? ex.ToString() : "N/A"), 2); - } -#endif - - //https://stackoverflow.com/questions/27108264/how-to-properly-make-a-http-web-get-request - - private static string HttpGetInternal(string uri) - { - HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); - request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; - - using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) - { - using (Stream stream = response.GetResponseStream()) - { - using (StreamReader reader = new StreamReader(stream)) - { - return reader.ReadToEnd(); - } - } - } - } - public static string HttpGet(string uri) - { - int tries = 0; - int triesMax = 5; - string exceptionMessage = ""; - - while (tries < triesMax) - { - tries++; - try - { - return HttpGetInternal(uri); - } - catch (Exception ex) - { -#if URI || LAUNCHER || BASICLAUNCHER - LogExceptions(ex); -#endif - exceptionMessage = ex.Message; - continue; - } } - return "ERROR: " + exceptionMessage; - } - - public static void DrawBorderSimple(Graphics graphics, Rectangle bounds, Color color, ButtonBorderStyle style, int width) - { - //AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - ControlPaint.DrawBorder(graphics, bounds, - color, width, style, - color, width, style, - color, width, style, - color, width, style); - } - - public static bool IsIPValid(string IP) - { - IPAddress address; - if (IPAddress.TryParse(IP, out address)) + public static void LogPrint(string text, int type = 1) { - switch (address.AddressFamily) + Logger log = LogManager.GetCurrentClassLogger(); + + switch (type) { - case System.Net.Sockets.AddressFamily.InterNetwork: - return true; - case System.Net.Sockets.AddressFamily.InterNetworkV6: + case 2: + log.Error(text); + break; + case 3: + log.Warn(text); + break; default: + log.Info(text); break; } } - return false; - } - - //converted from https://facreationz.wordpress.com/2014/12/11/c-know-if-running-under-wine/ - public static bool IsWineRunning() - { - string processName = "winlogon"; - var p = Process.GetProcessesByName(processName).Count(); - return (p <= 0); - } - - public static void ConsolePrint(string text, int type = 1, bool notime = false, bool noLog = false) - { - if (!notime) +#if LAUNCHER || URI || BASICLAUNCHER + public static void LogExceptions(Exception ex) { - ConsoleText("[" + DateTime.Now.ToShortTimeString() + "] - ", ConsoleColor.White); + string message = (ex.Message != null ? ex.Message.ToString() : "N/A"); + + ConsolePrint(ex.Source + " Exception: " + message, 2, false, true); + + LogPrint("EXCEPTION|MESSAGE: " + message, 2); + LogPrint("EXCEPTION|STACK TRACE: " + (!string.IsNullOrWhiteSpace(ex.StackTrace) ? ex.StackTrace : "N/A"), 2); + LogPrint("EXCEPTION|ADDITIONAL INFO: " + (ex != null ? ex.ToString() : "N/A"), 2); + } +#endif + + //https://stackoverflow.com/questions/27108264/how-to-properly-make-a-http-web-get-request + + private static string HttpGetInternal(string uri) + { + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); + request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + + using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) + { + using (Stream stream = response.GetResponseStream()) + { + using (StreamReader reader = new StreamReader(stream)) + { + return reader.ReadToEnd(); + } + } + } + } + public static string HttpGet(string uri) + { + int tries = 0; + int triesMax = 5; + string exceptionMessage = ""; + + while (tries < triesMax) + { + tries++; + try + { + return HttpGetInternal(uri); + } + catch (Exception ex) + { +#if URI || LAUNCHER || BASICLAUNCHER + LogExceptions(ex); +#endif + exceptionMessage = ex.Message; + continue; + } + } + + return "ERROR: " + exceptionMessage; } - switch (type) + public static void DrawBorderSimple(Graphics graphics, Rectangle bounds, Color color, ButtonBorderStyle style, int width) { - case 0: - ConsoleText(text, ConsoleColor.Black, true); - break; - case 2: - ConsoleText(text, ConsoleColor.Red, true); - if (!noLog) - LogPrint(text, 2); - break; - case 3: - ConsoleText(text, ConsoleColor.Green, true); - if (!noLog) - LogPrint(text); - break; - case 4: - ConsoleText(text, ConsoleColor.Cyan, true); - if (!noLog) - LogPrint(text); - break; - case 5: - ConsoleText(text, ConsoleColor.Yellow, true); - if (!noLog) - LogPrint(text, 3); - break; - case 1: - default: - ConsoleText(text, ConsoleColor.White, true); - if (!noLog) - LogPrint(text); - break; + //AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + ControlPaint.DrawBorder(graphics, bounds, + color, width, style, + color, width, style, + color, width, style, + color, width, style); } + public static bool IsIPValid(string IP) + { + IPAddress address; + if (IPAddress.TryParse(IP, out address)) + { + switch (address.AddressFamily) + { + case System.Net.Sockets.AddressFamily.InterNetwork: + return true; + case System.Net.Sockets.AddressFamily.InterNetworkV6: + default: + break; + } + } + + return false; + } + + //converted from https://facreationz.wordpress.com/2014/12/11/c-know-if-running-under-wine/ + public static bool IsWineRunning() + { + string processName = "winlogon"; + var p = Process.GetProcessesByName(processName).Count(); + return (p <= 0); + } + + public static void ConsolePrint(string text, int type = 1, bool notime = false, bool noLog = false) + { + if (!notime) + { + ConsoleText("[" + DateTime.Now.ToShortTimeString() + "] - ", ConsoleColor.White); + } + + switch (type) + { + case 0: + ConsoleText(text, ConsoleColor.Black, true); + break; + case 2: + ConsoleText(text, ConsoleColor.Red, true); + if (!noLog) + LogPrint(text, 2); + break; + case 3: + ConsoleText(text, ConsoleColor.Green, true); + if (!noLog) + LogPrint(text); + break; + case 4: + ConsoleText(text, ConsoleColor.Cyan, true); + if (!noLog) + LogPrint(text); + break; + case 5: + ConsoleText(text, ConsoleColor.Yellow, true); + if (!noLog) + LogPrint(text, 3); + break; + case 1: + default: + ConsoleText(text, ConsoleColor.White, true); + if (!noLog) + LogPrint(text); + break; + } + #if LAUNCHER if (GlobalVars.consoleForm != null) { FormPrint(text, type, GlobalVars.consoleForm.ConsoleBox, notime); } #endif - } - - public static void ConsolePrintMultiLine(string text, int type = 1, bool notime = false, bool noLog = false) - { - try - { - string[] NewlineChars = {Environment.NewLine, "\n"}; - string[] lines = text.Split(NewlineChars, StringSplitOptions.None); - ConsolePrintMultiLine(lines, type, notime, noLog); - } - catch (Exception e) - { -#if URI || LAUNCHER || BASICLAUNCHER - LogExceptions(e); -#endif - } - } - - public static void ConsolePrintMultiLine(ICollection textColection, int type = 1, bool notime = false, bool noLog = false) - { - if (!textColection.Any()) - return; - - if (textColection.Count == 1) - { - ConsolePrint(textColection.First(), type, notime, noLog); - return; } - foreach (string text in textColection) - { - ConsolePrint(text, type, notime, noLog); - } - } - - private static void FormPrint(string text, int type, RichTextBox box, bool noTime = false) - { - if (box == null) - return; - - if (!noTime) - { - box.AppendText("[" + DateTime.Now.ToShortTimeString() + "] - ", Color.White); - } - - switch (type) - { - case 1: - box.AppendText(text, Color.White); - break; - case 2: - box.AppendText(text, Color.Red); - break; - case 3: - box.AppendText(text, Color.Lime); - break; - case 4: - box.AppendText(text, Color.Aqua); - break; - case 5: - box.AppendText(text, Color.Yellow); - break; - case 0: - default: - box.AppendText(text, Color.Black); - break; - } - - box.AppendText(Environment.NewLine, Color.White); - } - - private static void ConsoleText(string text, ConsoleColor color, bool newLine = false) - { - Console.ForegroundColor = color; - if (newLine) - { - Console.WriteLine(text); - } - else - { - Console.Write(text); - } - } - - public static void ReadTextFileWithColor(string path) - { - var lines = File.ReadLines(path); - foreach (var line in lines) + public static void ConsolePrintMultiLine(string text, int type = 1, bool notime = false, bool noLog = false) { try { - string[] vals = line.Split('|'); - ConsolePrint(vals[0], Convert.ToInt32(vals[1]), true, true); + string[] NewlineChars = { Environment.NewLine, "\n" }; + string[] lines = text.Split(NewlineChars, StringSplitOptions.None); + ConsolePrintMultiLine(lines, type, notime, noLog); } - catch (Exception) + catch (Exception e) { - ConsolePrint(line, 1, true, true); +#if URI || LAUNCHER || BASICLAUNCHER + LogExceptions(e); +#endif + } + } + + public static void ConsolePrintMultiLine(ICollection textColection, int type = 1, bool notime = false, bool noLog = false) + { + if (!textColection.Any()) + return; + + if (textColection.Count == 1) + { + ConsolePrint(textColection.First(), type, notime, noLog); + return; + } + + foreach (string text in textColection) + { + ConsolePrint(text, type, notime, noLog); + } + } + + private static void FormPrint(string text, int type, RichTextBox box, bool noTime = false) + { + if (box == null) + return; + + if (!noTime) + { + box.AppendText("[" + DateTime.Now.ToShortTimeString() + "] - ", Color.White); + } + + switch (type) + { + case 1: + box.AppendText(text, Color.White); + break; + case 2: + box.AppendText(text, Color.Red); + break; + case 3: + box.AppendText(text, Color.Lime); + break; + case 4: + box.AppendText(text, Color.Aqua); + break; + case 5: + box.AppendText(text, Color.Yellow); + break; + case 0: + default: + box.AppendText(text, Color.Black); + break; + } + + box.AppendText(Environment.NewLine, Color.White); + } + + private static void ConsoleText(string text, ConsoleColor color, bool newLine = false) + { + Console.ForegroundColor = color; + if (newLine) + { + Console.WriteLine(text); + } + else + { + Console.Write(text); + } + } + + public static void ReadTextFileWithColor(string path) + { + var lines = File.ReadLines(path); + foreach (var line in lines) + { + try + { + string[] vals = line.Split('|'); + ConsolePrint(vals[0], Convert.ToInt32(vals[1]), true, true); + } + catch (Exception) + { + ConsolePrint(line, 1, true, true); + } } } - } #if LAUNCHER //https://stackoverflow.com/questions/30687987/unable-to-decompress-bz2-file-has-orginal-file-using-dotnetzip-library @@ -903,164 +905,165 @@ public static class Util dest.Write(buffer, 0, n); } #endif - #endregion + #endregion #if !BASICLAUNCHER - #region UPnP - public static void InitUPnP() - { - if (GlobalVars.UserConfiguration.UPnP) + #region UPnP + public static void InitUPnP() { - try + if (GlobalVars.UserConfiguration.UPnP) { - NetFuncs.InitUPnP(DeviceFound, DeviceLost); - ConsolePrint("UPnP: Service initialized", 3); - } - catch (Exception ex) - { - LogExceptions(ex); - ConsolePrint("UPnP: Unable to initialize UPnP. Reason - " + ex.Message, 2); + try + { + NetFuncs.InitUPnP(DeviceFound, DeviceLost); + ConsolePrint("UPnP: Service initialized", 3); + } + catch (Exception ex) + { + LogExceptions(ex); + ConsolePrint("UPnP: Unable to initialize UPnP. Reason - " + ex.Message, 2); + } } } - } - public static void StartUPnP(INatDevice device, Protocol protocol, int port) - { - if (GlobalVars.UserConfiguration.UPnP) + public static void StartUPnP(INatDevice device, Protocol protocol, int port) + { + if (GlobalVars.UserConfiguration.UPnP) + { + try + { + NetFuncs.StartUPnP(device, protocol, port); + string IP = !string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : device.GetExternalIP().ToString(); + ConsolePrint("UPnP: Port " + port + " opened on '" + IP + "' (" + protocol.ToString() + ")", 3); + } + catch (Exception ex) + { + LogExceptions(ex); + ConsolePrint("UPnP: Unable to open port mapping. Reason - " + ex.Message, 2); + } + } + } + + public static void StopUPnP(INatDevice device, Protocol protocol, int port) + { + if (GlobalVars.UserConfiguration.UPnP) + { + try + { + NetFuncs.StopUPnP(device, protocol, port); + string IP = !string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : device.GetExternalIP().ToString(); + ConsolePrint("UPnP: Port " + port + " closed on '" + IP + "' (" + protocol.ToString() + ")", 3); + } + catch (Exception ex) + { + LogExceptions(ex); + ConsolePrint("UPnP: Unable to close port mapping. Reason - " + ex.Message, 2); + } + } + } + + public static void DeviceFound(object sender, DeviceEventArgs args) { try { - NetFuncs.StartUPnP(device, protocol, port); + INatDevice device = args.Device; string IP = !string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : device.GetExternalIP().ToString(); - ConsolePrint("UPnP: Port " + port + " opened on '" + IP + "' (" + protocol.ToString() + ")", 3); + ConsolePrint("UPnP: Device '" + IP + "' registered.", 3); + StartUPnP(device, Protocol.Udp, GlobalVars.UserConfiguration.RobloxPort); + StartUPnP(device, Protocol.Tcp, GlobalVars.UserConfiguration.RobloxPort); } catch (Exception ex) { LogExceptions(ex); - ConsolePrint("UPnP: Unable to open port mapping. Reason - " + ex.Message, 2); + ConsolePrint("UPnP: Unable to register device. Reason - " + ex.Message, 2); } } - } - public static void StopUPnP(INatDevice device, Protocol protocol, int port) - { - if (GlobalVars.UserConfiguration.UPnP) + public static void DeviceLost(object sender, DeviceEventArgs args) { try { - NetFuncs.StopUPnP(device, protocol, port); + INatDevice device = args.Device; string IP = !string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : device.GetExternalIP().ToString(); - ConsolePrint("UPnP: Port " + port + " closed on '" + IP + "' (" + protocol.ToString() + ")", 3); + ConsolePrint("UPnP: Device '" + IP + "' disconnected.", 3); + StopUPnP(device, Protocol.Udp, GlobalVars.UserConfiguration.RobloxPort); + StopUPnP(device, Protocol.Tcp, GlobalVars.UserConfiguration.RobloxPort); } catch (Exception ex) { LogExceptions(ex); - ConsolePrint("UPnP: Unable to close port mapping. Reason - " + ex.Message, 2); + ConsolePrint("UPnP: Unable to disconnect device. Reason - " + ex.Message, 2); } } - } + #endregion - public static void DeviceFound(object sender, DeviceEventArgs args) - { - try + #region Discord + public static void ReadyCallback() { - INatDevice device = args.Device; - string IP = !string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : device.GetExternalIP().ToString(); - ConsolePrint("UPnP: Device '" + IP + "' registered.", 3); - StartUPnP(device, Protocol.Udp, GlobalVars.UserConfiguration.RobloxPort); - StartUPnP(device, Protocol.Tcp, GlobalVars.UserConfiguration.RobloxPort); + ConsolePrint("Discord RPC: Ready", 3); } - catch (Exception ex) + + public static void DisconnectedCallback(int errorCode, string message) { - LogExceptions(ex); - ConsolePrint("UPnP: Unable to register device. Reason - " + ex.Message, 2); + ConsolePrint("Discord RPC: Disconnected. Reason - " + errorCode + ": " + message, 2); } - } - public static void DeviceLost(object sender, DeviceEventArgs args) - { - try + public static void ErrorCallback(int errorCode, string message) { - INatDevice device = args.Device; - string IP = !string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : device.GetExternalIP().ToString(); - ConsolePrint("UPnP: Device '" + IP + "' disconnected.", 3); - StopUPnP(device, Protocol.Udp, GlobalVars.UserConfiguration.RobloxPort); - StopUPnP(device, Protocol.Tcp, GlobalVars.UserConfiguration.RobloxPort); + ConsolePrint("Discord RPC: Error. Reason - " + errorCode + ": " + message, 2); } - catch (Exception ex) + + public static void JoinCallback(string secret) { - LogExceptions(ex); - ConsolePrint("UPnP: Unable to disconnect device. Reason - " + ex.Message, 2); } - } - #endregion - #region Discord - public static void ReadyCallback() - { - ConsolePrint("Discord RPC: Ready", 3); - } - - public static void DisconnectedCallback(int errorCode, string message) - { - ConsolePrint("Discord RPC: Disconnected. Reason - " + errorCode + ": " + message, 2); - } - - public static void ErrorCallback(int errorCode, string message) - { - ConsolePrint("Discord RPC: Error. Reason - " + errorCode + ": " + message, 2); - } - - public static void JoinCallback(string secret) - { - } - - public static void SpectateCallback(string secret) - { - } - - public static void RequestCallback(DiscordRPC.JoinRequest request) - { - } - - public static void StartDiscord() - { - if (GlobalVars.UserConfiguration.DiscordPresence) + public static void SpectateCallback(string secret) { - GlobalVars.handlers = new DiscordRPC.EventHandlers(); - GlobalVars.handlers.readyCallback = ReadyCallback; - GlobalVars.handlers.disconnectedCallback += DisconnectedCallback; - GlobalVars.handlers.errorCallback += ErrorCallback; - GlobalVars.handlers.joinCallback += JoinCallback; - GlobalVars.handlers.spectateCallback += SpectateCallback; - GlobalVars.handlers.requestCallback += RequestCallback; - DiscordRPC.Initialize(GlobalVars.appid, ref GlobalVars.handlers, true, ""); - ConsolePrint("Discord RPC: Initalized", 3); - - ClientManagement.UpdateRichPresence(ClientManagement.GetStateForType(GlobalVars.GameOpened), true); } - } - #endregion + + public static void RequestCallback(DiscordRPC.JoinRequest request) + { + } + + public static void StartDiscord() + { + if (GlobalVars.UserConfiguration.DiscordPresence) + { + GlobalVars.handlers = new DiscordRPC.EventHandlers(); + GlobalVars.handlers.readyCallback = ReadyCallback; + GlobalVars.handlers.disconnectedCallback += DisconnectedCallback; + GlobalVars.handlers.errorCallback += ErrorCallback; + GlobalVars.handlers.joinCallback += JoinCallback; + GlobalVars.handlers.spectateCallback += SpectateCallback; + GlobalVars.handlers.requestCallback += RequestCallback; + DiscordRPC.Initialize(GlobalVars.appid, ref GlobalVars.handlers, true, ""); + ConsolePrint("Discord RPC: Initalized", 3); + + ClientManagement.UpdateRichPresence(ClientManagement.GetStateForType(GlobalVars.GameOpened), true); + } + } + #endregion #endif -} -#endregion - -#region Tab Control without Header -//https://stackoverflow.com/questions/23247941/c-sharp-how-to-remove-tabcontrol-border - -public partial class TabControlWithoutHeader : TabControl -{ - public TabControlWithoutHeader() - { - if (!DesignMode) Multiline = true; } + #endregion - protected override void WndProc(ref Message m) + #region Tab Control without Header + //https://stackoverflow.com/questions/23247941/c-sharp-how-to-remove-tabcontrol-border + + public partial class TabControlWithoutHeader : TabControl { - if (m.Msg == 0x1328 && !DesignMode) - m.Result = new IntPtr(1); - else - base.WndProc(ref m); + public TabControlWithoutHeader() + { + if (!DesignMode) Multiline = true; + } + + protected override void WndProc(ref Message m) + { + if (m.Msg == 0x1328 && !DesignMode) + m.Result = new IntPtr(1); + else + base.WndProc(ref m); + } } -} -#endregion \ No newline at end of file + #endregion +} \ No newline at end of file diff --git a/Novetus/NovetusLauncher/Classes/Launcher/ModManager.cs b/Novetus/NovetusLauncher/Classes/Launcher/ModManager.cs index bf9be1c..498b709 100644 --- a/Novetus/NovetusLauncher/Classes/Launcher/ModManager.cs +++ b/Novetus/NovetusLauncher/Classes/Launcher/ModManager.cs @@ -1,5 +1,6 @@ #region Usings using Ionic.Zip; +using Novetus.Core; using System; using System.Collections.Generic; using System.IO; diff --git a/Novetus/NovetusLauncher/Classes/Launcher/SplashLoader.cs b/Novetus/NovetusLauncher/Classes/Launcher/SplashLoader.cs index 6630afb..f94c366 100644 --- a/Novetus/NovetusLauncher/Classes/Launcher/SplashLoader.cs +++ b/Novetus/NovetusLauncher/Classes/Launcher/SplashLoader.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Collections.Generic; using System.Globalization; diff --git a/Novetus/NovetusLauncher/Classes/Launcher/TreeNodeHelper.cs b/Novetus/NovetusLauncher/Classes/Launcher/TreeNodeHelper.cs index fc2445f..c037963 100644 --- a/Novetus/NovetusLauncher/Classes/Launcher/TreeNodeHelper.cs +++ b/Novetus/NovetusLauncher/Classes/Launcher/TreeNodeHelper.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Collections.Generic; using System.IO; diff --git a/Novetus/NovetusLauncher/Forms/CustomGraphicsOptions.cs b/Novetus/NovetusLauncher/Forms/CustomGraphicsOptions.cs index 6018ab7..50d46e5 100644 --- a/Novetus/NovetusLauncher/Forms/CustomGraphicsOptions.cs +++ b/Novetus/NovetusLauncher/Forms/CustomGraphicsOptions.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Diagnostics; using System.IO; diff --git a/Novetus/NovetusLauncher/Forms/Decoder.cs b/Novetus/NovetusLauncher/Forms/Decoder.cs index bb10e48..8fdbd29 100644 --- a/Novetus/NovetusLauncher/Forms/Decoder.cs +++ b/Novetus/NovetusLauncher/Forms/Decoder.cs @@ -1,4 +1,5 @@ -using System.Windows.Forms; +using Novetus.Core; +using System.Windows.Forms; namespace NovetusLauncher { diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/Compact/LauncherFormCompact.Designer.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/Compact/LauncherFormCompact.Designer.cs index e5b3597..c9d1138 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/Compact/LauncherFormCompact.Designer.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/Compact/LauncherFormCompact.Designer.cs @@ -6,6 +6,8 @@ * * To change this template use Tools | Options | Coding | Edit Standard Headers. */ +using Novetus.Core; + namespace NovetusLauncher { partial class LauncherFormCompact diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/Compact/LauncherFormCompact.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/Compact/LauncherFormCompact.cs index 63e2e34..94ed02a 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/Compact/LauncherFormCompact.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/Compact/LauncherFormCompact.cs @@ -1,5 +1,6 @@ #region Usings using Mono.Nat; +using Novetus.Core; using System; using System.Collections.Generic; using System.ComponentModel; diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/Extended/LauncherFormExtended.Designer.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/Extended/LauncherFormExtended.Designer.cs index cbdd906..a70ad78 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/Extended/LauncherFormExtended.Designer.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/Extended/LauncherFormExtended.Designer.cs @@ -6,6 +6,8 @@ * * To change this template use Tools | Options | Coding | Edit Standard Headers. */ +using Novetus.Core; + namespace NovetusLauncher { partial class LauncherFormExtended diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/Extended/LauncherFormExtended.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/Extended/LauncherFormExtended.cs index 2c77821..3a8d06c 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/Extended/LauncherFormExtended.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/Extended/LauncherFormExtended.cs @@ -10,6 +10,7 @@ using System.Reflection; using Mono.Nat; using System.Globalization; using System.Linq; +using Novetus.Core; #endregion namespace NovetusLauncher diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs index 7ca63ac..8ae7da9 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs @@ -1,5 +1,6 @@ #region Usings using Mono.Nat; +using Novetus.Core; using System; using System.Collections.Generic; using System.ComponentModel; diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylish.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylish.cs index 412afbc..81849fe 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylish.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylish.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Collections.Generic; using System.ComponentModel; diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylishInterface.xaml.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylishInterface.xaml.cs index 5aa55c0..ea892f6 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylishInterface.xaml.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylishInterface.xaml.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Collections.Generic; using System.IO; diff --git a/Novetus/NovetusLauncher/Forms/LauncherFormSettings.cs b/Novetus/NovetusLauncher/Forms/LauncherFormSettings.cs index d1beb4f..47fa25c 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherFormSettings.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherFormSettings.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Diagnostics; using System.Windows.Forms; diff --git a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs index 57096aa..3d11775 100644 --- a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs +++ b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs @@ -10,6 +10,7 @@ using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using NLog; +using Novetus.Core; namespace NovetusLauncher { diff --git a/Novetus/NovetusLauncher/Forms/SDK/AssetDownloader.cs b/Novetus/NovetusLauncher/Forms/SDK/AssetDownloader.cs index d56fc14..c83b2c5 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/AssetDownloader.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/AssetDownloader.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Collections.Generic; using System.ComponentModel; diff --git a/Novetus/NovetusLauncher/Forms/SDK/AssetFixer.cs b/Novetus/NovetusLauncher/Forms/SDK/AssetFixer.cs index 3570ba5..fd8b1c0 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/AssetFixer.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/AssetFixer.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Collections.Generic; using System.ComponentModel; diff --git a/Novetus/NovetusLauncher/Forms/SDK/ClientScriptDocumentation.cs b/Novetus/NovetusLauncher/Forms/SDK/ClientScriptDocumentation.cs index bea14d0..76f4103 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/ClientScriptDocumentation.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/ClientScriptDocumentation.cs @@ -2,10 +2,11 @@ using System; using System.Windows.Forms; using System.IO; +using Novetus.Core; #endregion #region ClientScriptDocumentation - public partial class ClientScriptDocumentation : Form +public partial class ClientScriptDocumentation : Form { #region Constructor public ClientScriptDocumentation() diff --git a/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.cs b/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.cs index 16a2905..387d3c4 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.cs @@ -4,6 +4,7 @@ using System.Windows.Forms; using System.IO; using System.Globalization; using System.Collections.Generic; +using Novetus.Core; #endregion #region Client SDK diff --git a/Novetus/NovetusLauncher/Forms/SDK/DiogenesEditor.cs b/Novetus/NovetusLauncher/Forms/SDK/DiogenesEditor.cs index ba88b93..210fc6b 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/DiogenesEditor.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/DiogenesEditor.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.IO; using System.Text; diff --git a/Novetus/NovetusLauncher/Forms/SDK/ItemCreationSDK.cs b/Novetus/NovetusLauncher/Forms/SDK/ItemCreationSDK.cs index 962c673..11aea90 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/ItemCreationSDK.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/ItemCreationSDK.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Collections.Generic; using System.Drawing; diff --git a/Novetus/NovetusLauncher/Forms/SDK/ItemCreationSDKColorMenu.cs b/Novetus/NovetusLauncher/Forms/SDK/ItemCreationSDKColorMenu.cs index 1975604..2e03d2f 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/ItemCreationSDKColorMenu.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/ItemCreationSDKColorMenu.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Windows.Forms; #endregion diff --git a/Novetus/NovetusLauncher/Forms/SDK/MeshConverter.cs b/Novetus/NovetusLauncher/Forms/SDK/MeshConverter.cs index 3253719..cc7d8a2 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/MeshConverter.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/MeshConverter.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Collections.Generic; using System.ComponentModel; diff --git a/Novetus/NovetusLauncher/Forms/SDK/ModCreator.cs b/Novetus/NovetusLauncher/Forms/SDK/ModCreator.cs index b7d3167..60e4a3f 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/ModCreator.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/ModCreator.cs @@ -1,4 +1,5 @@ -using System; +using Novetus.Core; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; diff --git a/Novetus/NovetusLauncher/Forms/SDK/NovetusSDK.cs b/Novetus/NovetusLauncher/Forms/SDK/NovetusSDK.cs index bb29d2a..58263f7 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/NovetusSDK.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/NovetusSDK.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Collections.Generic; using System.ComponentModel; diff --git a/Novetus/NovetusLauncher/Forms/SDK/SplashTester.cs b/Novetus/NovetusLauncher/Forms/SDK/SplashTester.cs index efde336..265b9f5 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/SplashTester.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/SplashTester.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Drawing; using System.Linq; diff --git a/Novetus/NovetusLauncher/Forms/SDK/XMLContentEditor.cs b/Novetus/NovetusLauncher/Forms/SDK/XMLContentEditor.cs index 08e6018..fe06ed8 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/XMLContentEditor.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/XMLContentEditor.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Collections.Generic; using System.IO; diff --git a/Novetus/NovetusLauncher/Forms/ServerBrowser.cs b/Novetus/NovetusLauncher/Forms/ServerBrowser.cs index 150f28f..6e0d7eb 100644 --- a/Novetus/NovetusLauncher/Forms/ServerBrowser.cs +++ b/Novetus/NovetusLauncher/Forms/ServerBrowser.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Collections.Generic; using System.Drawing; diff --git a/Novetus/NovetusLauncher/NovetusLauncherEntryPoint.cs b/Novetus/NovetusLauncher/NovetusLauncherEntryPoint.cs index 44e7fb1..c2f0efb 100644 --- a/Novetus/NovetusLauncher/NovetusLauncherEntryPoint.cs +++ b/Novetus/NovetusLauncher/NovetusLauncherEntryPoint.cs @@ -1,5 +1,6 @@ #region Usings using NLog; +using Novetus.Core; using System; using System.Diagnostics; using System.Globalization; diff --git a/Novetus/NovetusURI/Classes/LocalFuncs.cs b/Novetus/NovetusURI/Classes/LocalFuncs.cs index af16a46..eb5c888 100644 --- a/Novetus/NovetusURI/Classes/LocalFuncs.cs +++ b/Novetus/NovetusURI/Classes/LocalFuncs.cs @@ -1,5 +1,6 @@ #region Usings using Microsoft.Win32; +using Novetus.Core; using System; using System.IO; using System.Windows.Forms; diff --git a/Novetus/NovetusURI/Forms/InstallForm.cs b/Novetus/NovetusURI/Forms/InstallForm.cs index 7962a0f..0904332 100644 --- a/Novetus/NovetusURI/Forms/InstallForm.cs +++ b/Novetus/NovetusURI/Forms/InstallForm.cs @@ -1,4 +1,5 @@ #region Usings +using Novetus.Core; using System; using System.Windows.Forms; #endregion diff --git a/Novetus/NovetusURI/Forms/LoaderForm.cs b/Novetus/NovetusURI/Forms/LoaderForm.cs index 6ebc1da..29cba58 100644 --- a/Novetus/NovetusURI/Forms/LoaderForm.cs +++ b/Novetus/NovetusURI/Forms/LoaderForm.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Threading; using System.Windows.Forms; using NLog; +using Novetus.Core; #endregion namespace NovetusURI diff --git a/Novetus/NovetusURI/Forms/QuickConfigure.cs b/Novetus/NovetusURI/Forms/QuickConfigure.cs index 76ba01e..cbb8507 100644 --- a/Novetus/NovetusURI/Forms/QuickConfigure.cs +++ b/Novetus/NovetusURI/Forms/QuickConfigure.cs @@ -3,6 +3,7 @@ using System; using System.Windows.Forms; using System.ComponentModel; using System.Drawing; +using Novetus.Core; #endregion namespace NovetusURI diff --git a/Novetus/NovetusURI/NovetusURI.cs b/Novetus/NovetusURI/NovetusURI.cs index f4bdc65..f5b0483 100644 --- a/Novetus/NovetusURI/NovetusURI.cs +++ b/Novetus/NovetusURI/NovetusURI.cs @@ -1,5 +1,6 @@ #region Usings using NLog; +using Novetus.Core; using System; using System.IO; using System.Threading; -- 2.40.1 From 39f99b147090dbd93e0d02308c82ef967815b53d Mon Sep 17 00:00:00 2001 From: Bitl Date: Thu, 5 Jan 2023 11:02:55 -0700 Subject: [PATCH 14/85] functional scripts!!! --- Novetus/NovetusCore/Classes/Script.cs | 10 +++---- Novetus/NovetusCore/Classes/WebProxy.cs | 39 ++++++++++++++----------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/Novetus/NovetusCore/Classes/Script.cs b/Novetus/NovetusCore/Classes/Script.cs index d8b9525..b0caa45 100644 --- a/Novetus/NovetusCore/Classes/Script.cs +++ b/Novetus/NovetusCore/Classes/Script.cs @@ -81,7 +81,7 @@ error: foreach (CompilerError error in result.Errors) { - ErrorHandler(error, filePath, error.IsWarning, false); + ErrorHandler(error, filePath, error.IsWarning); } if (result.Errors.HasErrors) @@ -92,17 +92,17 @@ error: return result.CompiledAssembly; } - public static void ErrorHandler(string error, bool finalError = false) + public static void ErrorHandler(string error) { - ErrorHandler(error, false, finalError); + ErrorHandler(error, false); } - private static void ErrorHandler(string error, bool warning, bool finalError) + private static void ErrorHandler(string error, bool warning) { Util.ConsolePrint(warning ? "[SCRIPT WARNING] - " : "[SCRIPT ERROR] - " + error, warning ? 5 : 2); } - private static void ErrorHandler(CompilerError error, string fileName, bool warning, bool finalError) + private static void ErrorHandler(CompilerError error, string fileName, bool warning) { Util.ConsolePrint(warning ? "[SCRIPT WARNING] - " : "[SCRIPT ERROR] - " + fileName + " (" + error.Line + "," + error.Column + "): " + error.ErrorText, warning ? 5 : 2); } diff --git a/Novetus/NovetusCore/Classes/WebProxy.cs b/Novetus/NovetusCore/Classes/WebProxy.cs index 31892b3..89dd76e 100644 --- a/Novetus/NovetusCore/Classes/WebProxy.cs +++ b/Novetus/NovetusCore/Classes/WebProxy.cs @@ -16,7 +16,7 @@ namespace Novetus.Core { public class IWebProxyExtension { - public virtual string Name { get; set; } = "Unnamed Web Proxy Extension"; + public virtual string Name() { return "Unnamed Web Proxy Extension"; } public virtual void OnExtensionLoad() { } public virtual void OnProxyStart() { } public virtual void OnProxyStopped() { } @@ -24,9 +24,7 @@ namespace Novetus.Core public virtual bool IsValidURL(string absolutePath, string host) { return false; } public virtual Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) { return Task.CompletedTask; } -#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously - public virtual async Task OnRequest(object sender, SessionEventArgs e) { } -#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously + public virtual Task OnRequest(object sender, SessionEventArgs e) { return Task.CompletedTask; } } public class WebProxy @@ -60,12 +58,12 @@ namespace Novetus.Core { IWebProxyExtension newExt = (IWebProxyExtension)Script.LoadScriptFromContent(file); ExtensionList.Add(newExt); - Util.ConsolePrint("Web Proxy: Loaded extension " + newExt.Name + " from " + Path.GetFileName(file), 3); + Util.ConsolePrint("Web Proxy: Loaded extension " + newExt.Name() + " from " + Path.GetFileName(file), 3); newExt.OnExtensionLoad(); } - catch (Exception e) + catch (Exception) { - Util.LogExceptions(e); + Util.ConsolePrint("Web Proxy: Failed to load script " + Path.GetFileName(file), 2); } } } @@ -121,9 +119,16 @@ namespace Novetus.Core Server.BeforeRequest += new AsyncEventHandler(OnRequest); UpdateEndPoint(true); Util.ConsolePrint("Web Proxy started on port " + GlobalVars.WebProxyPort, 3); - foreach (IWebProxyExtension extension in ExtensionList.ToArray()) + try { - extension.OnProxyStart(); + foreach (IWebProxyExtension extension in ExtensionList.ToArray()) + { + extension.OnProxyStart(); + } + } + catch (Exception ex) + { + Script.ErrorHandler(ex.Message); } } catch (Exception e) @@ -193,7 +198,7 @@ namespace Novetus.Core return (ua.Contains("mozilla/4.0") || ua.Contains("roblox")); } - private Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) + private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) { if (!IsValidURL(e.HttpClient)) { @@ -208,11 +213,11 @@ namespace Novetus.Core { try { - extension.OnBeforeTunnelConnectRequest(sender, e); + await extension.OnBeforeTunnelConnectRequest(sender, e); } catch (Exception ex) { - Util.LogExceptions(ex); + Script.ErrorHandler(ex.Message); } } else @@ -220,8 +225,6 @@ namespace Novetus.Core e.DecryptSsl = false; } } - - return Task.CompletedTask; } #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously @@ -246,7 +249,7 @@ namespace Novetus.Core } catch (Exception ex) { - Util.LogExceptions(ex); + Script.ErrorHandler(ex.Message); e.GenericResponse("", HttpStatusCode.InternalServerError); return; } @@ -268,11 +271,13 @@ namespace Novetus.Core { extension.OnProxyStopped(); } - catch (Exception e) + catch (Exception ex) { - Util.LogExceptions(e); + Script.ErrorHandler(ex.Message); } } + + ExtensionList.Clear(); } } } -- 2.40.1 From 3998afcc6204270606a69e74d83c7d68fd9c5c24 Mon Sep 17 00:00:00 2001 From: Bitl Date: Thu, 5 Jan 2023 11:14:09 -0700 Subject: [PATCH 15/85] updated files --- README-AND-CREDITS.TXT | 1 + changelog.txt | 10 ++++++++++ consolehelp.txt | 1 + scripts/batch/clean_junk.bat | 3 ++- 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/README-AND-CREDITS.TXT b/README-AND-CREDITS.TXT index b770b6a..6d0f604 100644 --- a/README-AND-CREDITS.TXT +++ b/README-AND-CREDITS.TXT @@ -309,6 +309,7 @@ Thank you Nukley for the idea of the Splash Tester. Credits go to Nostal-ia for getting 2011M corescripts working and helping me with 2011E corescripts. Credits to Hazelnut (creator of JRBX) for the buttons used in the Stylish style. Credits go to davcs86 for the HWID generation code (https://github.com/davcs86/csharp-uhwid) +Credits got to BRAVONATCHO and Sodikm for the web proxy code. All credits for the used pieces of code go to the respective authors. ------------------------------------------------------------ diff --git a/changelog.txt b/changelog.txt index c78551b..a9d963b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,13 @@ +1.3 Snapshot v22.8405.19856.1 +Enhancements: +- Added the Web Proxy! + - Novetus will now have a prompt on launch asking if the user would like to enable the web proxy. When pressing "Yes", the user will have to install the web proxy certificate on the next prompt. The initial prompt will only appear once. + - The proxy Console command is an additional way to turn on and turn off the web proxy. + - The Proxy is extendable with user scripts that enhance the client experience. + +Fixes: +- Fixed a bug where resetting the config would close the console. +---------------------------------------------------------------------------- 1.3 Snapshot v22.8391.14830.1 Notes: - As of the current Novetus version, .NET Framework 4.0 is no longer the main framework running Novetus. Novetus now requires .NET Framework 4.8. diff --git a/consolehelp.txt b/consolehelp.txt index 4648bcf..b9f8b7d 100644 --- a/consolehelp.txt +++ b/consolehelp.txt @@ -16,6 +16,7 @@ Commands:|3 + config save - Saves the config file|4 + config load - Reloads the config file|4 + config reset - Resets the config file|4 ++ proxy - Turns Novetus' web proxy on and off. ---------|1 Command-Line Parameters:|3 ---------|1 diff --git a/scripts/batch/clean_junk.bat b/scripts/batch/clean_junk.bat index 1ad6397..1330c2d 100644 --- a/scripts/batch/clean_junk.bat +++ b/scripts/batch/clean_junk.bat @@ -1,6 +1,5 @@ @ECHO OFF del /S Novetus\*.pdb -del /S Novetus\*.exe.config del /S Novetus\*.log del /S Novetus\*.bak @@ -125,6 +124,8 @@ del /s /q Novetus\config\clients\GlobalSettings7_2008M.xml del /s /q Novetus\config\clients\GlobalSettings_13_2012M.xml del /s /q Novetus\config\clients\GlobalSettings_4_2009L.xml +del /s /q Novetus\bin\rootCert.pfx + rmdir /s /q Novetus\maps\Custom rmdir /s /q Novetus\shareddata\assetcache rmdir /s /q Novetus\logs \ No newline at end of file -- 2.40.1 From c3f3a26dca485f571a5370a6c8aea7cd4f814746 Mon Sep 17 00:00:00 2001 From: Bitl Date: Thu, 5 Jan 2023 21:19:37 -0700 Subject: [PATCH 16/85] script engine changes. --- Novetus/NovetusCore/Classes/Script.cs | 32 +++++++++++++++---------- Novetus/NovetusCore/Classes/WebProxy.cs | 24 +++++++++---------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/Novetus/NovetusCore/Classes/Script.cs b/Novetus/NovetusCore/Classes/Script.cs index b0caa45..e8069b2 100644 --- a/Novetus/NovetusCore/Classes/Script.cs +++ b/Novetus/NovetusCore/Classes/Script.cs @@ -10,6 +10,17 @@ using System.Linq; // based on https://stackoverflow.com/questions/137933/what-is-the-best-scripting-language-to-embed-in-a-c-sharp-desktop-application namespace Novetus.Core { + #region IExtension + public class IExtension + { + public virtual string Name() { return "Unnamed Object"; } + public virtual string Version() { return "1.0.0"; } + public virtual string FullInfoString() { return (Name() + " v" + Version()); } + public virtual void OnExtensionLoad() { } + public virtual void OnExtensionUnload() { } + } + #endregion + #region Script public class Script { @@ -30,7 +41,7 @@ namespace Novetus.Core } catch (Exception ex) { - ErrorHandler(scriptPath + ": " + ex.ToString(), true); + ErrorHandler(scriptPath + ": " + ex.ToString()); } return null; @@ -56,13 +67,13 @@ namespace Novetus.Core } else { - ErrorHandler(filePath + ": Constructor does not exist or it is not public.", true); + ErrorHandler(filePath + ": Constructor does not exist or it is not public."); return null; } } error: - ErrorHandler(filePath + ": Failed to load script.", true); + ErrorHandler(filePath + ": Failed to load script."); return null; } @@ -81,7 +92,7 @@ error: foreach (CompilerError error in result.Errors) { - ErrorHandler(error, filePath, error.IsWarning); + ErrorHandler(error, filePath); } if (result.Errors.HasErrors) @@ -92,19 +103,14 @@ error: return result.CompiledAssembly; } - public static void ErrorHandler(string error) + private static void ErrorHandler(string error) { - ErrorHandler(error, false); + Util.ConsolePrint("[SCRIPT ERROR] - " + error, 2); } - private static void ErrorHandler(string error, bool warning) + private static void ErrorHandler(CompilerError error, string fileName) { - Util.ConsolePrint(warning ? "[SCRIPT WARNING] - " : "[SCRIPT ERROR] - " + error, warning ? 5 : 2); - } - - private static void ErrorHandler(CompilerError error, string fileName, bool warning) - { - Util.ConsolePrint(warning ? "[SCRIPT WARNING] - " : "[SCRIPT ERROR] - " + fileName + " (" + error.Line + "," + error.Column + "): " + error.ErrorText, warning ? 5 : 2); + Util.ConsolePrint("[SCRIPT ERROR] - " + fileName + " (" + error.Line + "," + error.Column + "): " + error.ErrorText, 2); } } #endregion diff --git a/Novetus/NovetusCore/Classes/WebProxy.cs b/Novetus/NovetusCore/Classes/WebProxy.cs index 89dd76e..c838b72 100644 --- a/Novetus/NovetusCore/Classes/WebProxy.cs +++ b/Novetus/NovetusCore/Classes/WebProxy.cs @@ -14,10 +14,8 @@ using Titanium.Web.Proxy.Models; namespace Novetus.Core { - public class IWebProxyExtension + public class IWebProxyExtension : IExtension { - public virtual string Name() { return "Unnamed Web Proxy Extension"; } - public virtual void OnExtensionLoad() { } public virtual void OnProxyStart() { } public virtual void OnProxyStopped() { } @@ -54,16 +52,21 @@ namespace Novetus.Core foreach (string file in filePaths) { + int index = 0; + try { IWebProxyExtension newExt = (IWebProxyExtension)Script.LoadScriptFromContent(file); ExtensionList.Add(newExt); - Util.ConsolePrint("Web Proxy: Loaded extension " + newExt.Name() + " from " + Path.GetFileName(file), 3); + index = ExtensionList.IndexOf(newExt); + Util.ConsolePrint("Web Proxy: Loaded extension " + newExt.FullInfoString() + " from " + Path.GetFileName(file), 3); newExt.OnExtensionLoad(); } catch (Exception) { Util.ConsolePrint("Web Proxy: Failed to load script " + Path.GetFileName(file), 2); + ExtensionList.RemoveAt(index); + continue; } } } @@ -126,9 +129,8 @@ namespace Novetus.Core extension.OnProxyStart(); } } - catch (Exception ex) + catch (Exception) { - Script.ErrorHandler(ex.Message); } } catch (Exception e) @@ -215,9 +217,8 @@ namespace Novetus.Core { await extension.OnBeforeTunnelConnectRequest(sender, e); } - catch (Exception ex) + catch (Exception) { - Script.ErrorHandler(ex.Message); } } else @@ -247,9 +248,8 @@ namespace Novetus.Core await extension.OnRequest(sender, e); return; } - catch (Exception ex) + catch (Exception) { - Script.ErrorHandler(ex.Message); e.GenericResponse("", HttpStatusCode.InternalServerError); return; } @@ -270,10 +270,10 @@ namespace Novetus.Core try { extension.OnProxyStopped(); + extension.OnExtensionUnload(); } - catch (Exception ex) + catch (Exception) { - Script.ErrorHandler(ex.Message); } } -- 2.40.1 From 1e7bffcd8aaba629ddc1dd37bd1bbbd24baed2fa Mon Sep 17 00:00:00 2001 From: Bitl Date: Thu, 5 Jan 2023 21:23:39 -0700 Subject: [PATCH 17/85] default request --- Novetus/NovetusCore/Classes/WebProxy.cs | 6 +++++- Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Novetus/NovetusCore/Classes/WebProxy.cs b/Novetus/NovetusCore/Classes/WebProxy.cs index c838b72..cd7f0eb 100644 --- a/Novetus/NovetusCore/Classes/WebProxy.cs +++ b/Novetus/NovetusCore/Classes/WebProxy.cs @@ -22,7 +22,11 @@ namespace Novetus.Core public virtual bool IsValidURL(string absolutePath, string host) { return false; } public virtual Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) { return Task.CompletedTask; } - public virtual Task OnRequest(object sender, SessionEventArgs e) { return Task.CompletedTask; } + public virtual Task OnRequest(object sender, SessionEventArgs e) + { + e.Ok("Test successful. \nRunning Novetus " + GlobalVars.ProgramInformation.Version + " on " + GlobalVars.ProgramInformation.NetVersion); + return Task.CompletedTask; + } } public class WebProxy diff --git a/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs b/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs index 7f0821b..5561fab 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs @@ -202,7 +202,7 @@ namespace Novetus.Core DefaultMap = ""; //HACK #if NET4 - NetVersion = ".NET 4.0"; + NetVersion = ".NET 4.0"; #elif NET481 NetVersion = ".NET 4.8"; #endif -- 2.40.1 From 79ecfafeb5f3e68b86884a68617f74a26fd71f65 Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 6 Jan 2023 12:03:47 -0700 Subject: [PATCH 18/85] improved console/extension reliability --- Novetus/NovetusCore/Classes/WebProxy.cs | 11 +++-- .../StorageAndFunctions/GlobalPaths.cs | 1 + .../StorageAndFunctions/NetFuncs.cs | 11 +++++ .../NovetusCore/StorageAndFunctions/Util.cs | 43 ++++++++----------- .../NovetusLauncher/Forms/NovetusConsole.cs | 11 +++-- 5 files changed, 43 insertions(+), 34 deletions(-) diff --git a/Novetus/NovetusCore/Classes/WebProxy.cs b/Novetus/NovetusCore/Classes/WebProxy.cs index cd7f0eb..cbb8f05 100644 --- a/Novetus/NovetusCore/Classes/WebProxy.cs +++ b/Novetus/NovetusCore/Classes/WebProxy.cs @@ -22,10 +22,9 @@ namespace Novetus.Core public virtual bool IsValidURL(string absolutePath, string host) { return false; } public virtual Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) { return Task.CompletedTask; } - public virtual Task OnRequest(object sender, SessionEventArgs e) + public virtual async Task OnRequest(object sender, SessionEventArgs e) { e.Ok("Test successful. \nRunning Novetus " + GlobalVars.ProgramInformation.Version + " on " + GlobalVars.ProgramInformation.NetVersion); - return Task.CompletedTask; } } @@ -227,7 +226,7 @@ namespace Novetus.Core } else { - e.DecryptSsl = false; + continue; } } } @@ -255,9 +254,13 @@ namespace Novetus.Core catch (Exception) { e.GenericResponse("", HttpStatusCode.InternalServerError); - return; + continue; } } + else + { + continue; + } } e.GenericResponse("", HttpStatusCode.NotFound); diff --git a/Novetus/NovetusCore/StorageAndFunctions/GlobalPaths.cs b/Novetus/NovetusCore/StorageAndFunctions/GlobalPaths.cs index 6373c1f..c34341d 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/GlobalPaths.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/GlobalPaths.cs @@ -15,6 +15,7 @@ namespace Novetus.Core public static readonly string RootPath = Directory.GetParent(RootPathLauncher).ToString(); public static readonly string BasePath = RootPath.Replace(@"\", @"\\"); public static readonly string DataPath = BasePath + @"\\shareddata"; + public static readonly string AssetsPath = BasePath + @"\\assets"; public static readonly string BinDir = BasePath + @"\\bin"; public static readonly string ConfigDir = BasePath + @"\\config"; public static readonly string LogDir = BasePath + @"\\logs"; diff --git a/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs b/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs index 7695849..292ca75 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs @@ -2,6 +2,7 @@ #region Usings using Mono.Nat; using System; +using System.Web; #endregion namespace Novetus.Core @@ -50,6 +51,16 @@ namespace Novetus.Core } } } + + public static string FindQueryString(Uri uri, string searchQuery) + { + return FindQueryString(uri.Query, searchQuery); + } + + public static string FindQueryString(string query, string searchQuery) + { + return HttpUtility.ParseQueryString(query)[searchQuery]; + } } #endregion } diff --git a/Novetus/NovetusCore/StorageAndFunctions/Util.cs b/Novetus/NovetusCore/StorageAndFunctions/Util.cs index e0237d7..3ba1ef1 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/Util.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/Util.cs @@ -44,7 +44,7 @@ namespace Novetus.Core box.SelectionColor = color; box.AppendText(text); - box.SelectionColor = box.ForeColor; + //box.SelectionColor = box.ForeColor; } #endregion @@ -592,7 +592,7 @@ namespace Novetus.Core { string message = (ex.Message != null ? ex.Message.ToString() : "N/A"); - ConsolePrint(ex.Source + " Exception: " + message, 2, false, true); + ConsolePrint(ex.Source + " Exception: " + message, 2, true); LogPrint("EXCEPTION|MESSAGE: " + message, 2); LogPrint("EXCEPTION|STACK TRACE: " + (!string.IsNullOrWhiteSpace(ex.StackTrace) ? ex.StackTrace : "N/A"), 2); @@ -680,13 +680,8 @@ namespace Novetus.Core return (p <= 0); } - public static void ConsolePrint(string text, int type = 1, bool notime = false, bool noLog = false) + public static void ConsolePrint(string text, int type = 1, bool noLog = false) { - if (!notime) - { - ConsoleText("[" + DateTime.Now.ToShortTimeString() + "] - ", ConsoleColor.White); - } - switch (type) { case 0: @@ -721,20 +716,20 @@ namespace Novetus.Core } #if LAUNCHER - if (GlobalVars.consoleForm != null) - { - FormPrint(text, type, GlobalVars.consoleForm.ConsoleBox, notime); - } + if (GlobalVars.consoleForm != null) + { + FormPrint(text, type, GlobalVars.consoleForm.ConsoleBox); + } #endif } - public static void ConsolePrintMultiLine(string text, int type = 1, bool notime = false, bool noLog = false) + public static void ConsolePrintMultiLine(string text, int type = 1, bool noLog = false) { try { string[] NewlineChars = { Environment.NewLine, "\n" }; string[] lines = text.Split(NewlineChars, StringSplitOptions.None); - ConsolePrintMultiLine(lines, type, notime, noLog); + ConsolePrintMultiLine(lines, type, noLog); } catch (Exception e) { @@ -744,33 +739,35 @@ namespace Novetus.Core } } - public static void ConsolePrintMultiLine(ICollection textColection, int type = 1, bool notime = false, bool noLog = false) + public static void ConsolePrintMultiLine(ICollection textColection, int type = 1, bool noLog = false) { if (!textColection.Any()) return; if (textColection.Count == 1) { - ConsolePrint(textColection.First(), type, notime, noLog); + ConsolePrint(textColection.First(), type, noLog); return; } foreach (string text in textColection) { - ConsolePrint(text, type, notime, noLog); + ConsolePrint(text, type, noLog); } } - private static void FormPrint(string text, int type, RichTextBox box, bool noTime = false) + private static void FormPrint(string text, int type, RichTextBox box) { if (box == null) return; - if (!noTime) + foreach (string line in box.Lines) { - box.AppendText("[" + DateTime.Now.ToShortTimeString() + "] - ", Color.White); + Regex.Replace(line, @"^\s+$[\r\n]*", "", RegexOptions.Multiline); } + box.AppendText("\r\n", Color.White); + switch (type) { case 1: @@ -793,8 +790,6 @@ namespace Novetus.Core box.AppendText(text, Color.Black); break; } - - box.AppendText(Environment.NewLine, Color.White); } private static void ConsoleText(string text, ConsoleColor color, bool newLine = false) @@ -818,11 +813,11 @@ namespace Novetus.Core try { string[] vals = line.Split('|'); - ConsolePrint(vals[0], Convert.ToInt32(vals[1]), true, true); + ConsolePrint(vals[0], Convert.ToInt32(vals[1]), true); } catch (Exception) { - ConsolePrint(line, 1, true, true); + ConsolePrint(line, 1, true); } } } diff --git a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs index 3d11775..1021212 100644 --- a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs +++ b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs @@ -441,16 +441,16 @@ namespace NovetusLauncher public void ConsoleHelp() { ClearConsole(); - Util.ConsolePrint("Help:", 3, true, true); + Util.ConsolePrint("Help:", 3, true); Util.ReadTextFileWithColor(GlobalPaths.BasePath + "\\" + GlobalPaths.ConsoleHelpFileName); - Util.ConsolePrint(GlobalVars.Important2, 0, true, true); + Util.ConsolePrint(GlobalVars.Important2, 0, true); ScrollToTop(); } public void ClientScriptDoc() { ClearConsole(); - Util.ConsolePrint("ClientScript Documentation:", 3, true, true); + Util.ConsolePrint("ClientScript Documentation:", 3, true); Util.ReadTextFileWithColor(GlobalPaths.BasePath + "\\" + GlobalPaths.ClientScriptDocumentationFileName); ScrollToTop(); } @@ -476,7 +476,6 @@ namespace NovetusLauncher if (e.KeyCode == Keys.Enter) { - ConsoleBox.AppendText(Environment.NewLine, Color.White); ConsoleProcessCommands(lastLine); e.Handled = true; } @@ -499,8 +498,8 @@ namespace NovetusLauncher private void ClearConsole() { ConsoleBox.Text = ""; - ConsoleBox.SelectionStart = 0; - ConsoleBox.ScrollToCaret(); + ScrollToTop(); + Console.Clear(); } private void ScrollToTop() -- 2.40.1 From eaecb76d7a038776f6f25b5f4a724b343143977c Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 6 Jan 2023 12:13:54 -0700 Subject: [PATCH 19/85] updates changelog and various files --- README-AND-CREDITS.TXT | 2 +- changelog.txt | 10 ++++++++++ scripts/launcher/info.ini | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/README-AND-CREDITS.TXT b/README-AND-CREDITS.TXT index 6d0f604..4be084b 100644 --- a/README-AND-CREDITS.TXT +++ b/README-AND-CREDITS.TXT @@ -309,7 +309,7 @@ Thank you Nukley for the idea of the Splash Tester. Credits go to Nostal-ia for getting 2011M corescripts working and helping me with 2011E corescripts. Credits to Hazelnut (creator of JRBX) for the buttons used in the Stylish style. Credits go to davcs86 for the HWID generation code (https://github.com/davcs86/csharp-uhwid) -Credits got to BRAVONATCHO and Sodikm for the web proxy code. +Credits go to BRAVONATCHO and Sodikm for parts of the web proxy code. All credits for the used pieces of code go to the respective authors. ------------------------------------------------------------ diff --git a/changelog.txt b/changelog.txt index a9d963b..c286554 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,13 @@ +1.3 Snapshot v22.8406.21589.1 +Enhancements: +- Added the following functionality to the Web Proxy: + - Asset Redirection + - Various web pages. + +Fixes: +- Fixed various stability issues with the Novetus Script Engine (used for Web Proxy Extensions). +- Improved the reliability and functionality of the Console when printing a large number of messages. +---------------------------------------------------------------------------- 1.3 Snapshot v22.8405.19856.1 Enhancements: - Added the Web Proxy! diff --git a/scripts/launcher/info.ini b/scripts/launcher/info.ini index e90a3fa..ff02e34 100644 --- a/scripts/launcher/info.ini +++ b/scripts/launcher/info.ini @@ -9,5 +9,5 @@ ExtendedVersionEditChangelog=True //ExtendedVersionTemplate=%version% v11.2022.%extended-revision%%lite% ExtendedVersionTemplate=%version% Snapshot v22.%build%.%revision%.%extended-revision% ExtendedVersionRevision=1 -InitialBootup=True +InitialBootup=False IsLite=False -- 2.40.1 From d37c43d8b0f4c7297e1a5b8e61bcdc43a6749886 Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 6 Jan 2023 12:17:40 -0700 Subject: [PATCH 20/85] add addons --- Asset.cs | 55 +++++++++++++++++++++++++++++++++++ StudioLaunchPage.cs | 28 ++++++++++++++++++ UploadWarnings.cs | 39 +++++++++++++++++++++++++ scripts/batch/github_sync.bat | 5 ++++ scripts/launcher/info.ini | 2 +- 5 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 Asset.cs create mode 100644 StudioLaunchPage.cs create mode 100644 UploadWarnings.cs diff --git a/Asset.cs b/Asset.cs new file mode 100644 index 0000000..ee8e3a8 --- /dev/null +++ b/Asset.cs @@ -0,0 +1,55 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using System.Web; +using System.Collections.Generic; +using Titanium.Web.Proxy; +using Titanium.Web.Proxy.EventArguments; +using Titanium.Web.Proxy.Http; +using Titanium.Web.Proxy.Models; +using Novetus.Core; + +public class Asset : IWebProxyExtension +{ + public override string Name() + { + return "Asset Redirection Extension"; + } + + public override bool IsValidURL(string absolutePath, string host) + { + return (absolutePath.EndsWith("/asset") || absolutePath.EndsWith("/asset/")); + } + + public override async Task OnRequest(object sender, SessionEventArgs e) + { + string query = e.HttpClient.Request.RequestUri.Query; + long id; + if (!long.TryParse(NetFuncs.FindQueryString(query, "id"), out id)) + { + Util.ConsolePrint(Name() + ": Redirecting " + query, 3); + e.Redirect("https://assetdelivery.roblox.com/v1/asset/" + query); + } + else + { + List PathList = new List((IEnumerable)Directory.GetFiles(GlobalPaths.DataPath, id.ToString(), SearchOption.AllDirectories)); + + if (PathList.Count > 0) + { + Util.ConsolePrint(Name() + ": Local assets for " + id.ToString() + " found. Redirecting " + query, 3); + string First = PathList[0]; + byte[] numArray = await Task.Run(() => File.ReadAllBytes(First)); + e.Ok(numArray, (IEnumerable) new List() + { + new HttpHeader("Content-Length", ((long) numArray.Length).ToString()), + new HttpHeader("Cache-Control", "no-cache") + }); + } + else + { + Util.ConsolePrint(Name() + ": No local assets for " + id.ToString() + ". Redirecting " + query, 5); + e.Redirect("https://assetdelivery.roblox.com/v1/asset/" + query); + } + } + } +} \ No newline at end of file diff --git a/StudioLaunchPage.cs b/StudioLaunchPage.cs new file mode 100644 index 0000000..dcb744c --- /dev/null +++ b/StudioLaunchPage.cs @@ -0,0 +1,28 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using System.Web; +using System.Collections.Generic; +using Titanium.Web.Proxy; +using Titanium.Web.Proxy.EventArguments; +using Titanium.Web.Proxy.Http; +using Titanium.Web.Proxy.Models; +using Novetus.Core; + +public class StudioLaunchPage : IWebProxyExtension +{ + public override string Name() + { + return "Studio Launch Page Extension"; + } + + public override bool IsValidURL(string absolutePath, string host) + { + return absolutePath.EndsWith("/ide/landing.aspx") || absolutePath.EndsWith("/my/places.aspx"); + } + + public override async Task OnRequest(object sender, SessionEventArgs e) + { + e.Ok("Welcome to Novetus Studio version " + GlobalVars.ProgramInformation.Version); + } +} \ No newline at end of file diff --git a/UploadWarnings.cs b/UploadWarnings.cs new file mode 100644 index 0000000..cac5430 --- /dev/null +++ b/UploadWarnings.cs @@ -0,0 +1,39 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using System.Web; +using System.Collections.Generic; +using Titanium.Web.Proxy; +using Titanium.Web.Proxy.EventArguments; +using Titanium.Web.Proxy.Http; +using Titanium.Web.Proxy.Models; +using Novetus.Core; + +public class UploadWarnings : IWebProxyExtension +{ + public override string Name() + { + return "Upload Dialog Warnings Extension"; + } + + public override bool IsValidURL(string absolutePath, string host) + { + return absolutePath.EndsWith("/uploadmedia/postimage.aspx") || absolutePath.EndsWith("/uploadmedia/uploadvideo.aspx"); + } + + public override async Task OnRequest(object sender, SessionEventArgs e) + { + string absPath = e.HttpClient.Request.RequestUri.AbsolutePath.ToLowerInvariant(); + + string type = "video"; + string folder = "Videos"; + + if (absPath.EndsWith("/uploadmedia/postimage.aspx")) + { + type = "screenshot"; + folder = "Pictures"; + } + + e.Ok("Your " + type + " was saved! Look in the Roblox folder in your " + folder + " folder!"); + } +} \ No newline at end of file diff --git a/scripts/batch/github_sync.bat b/scripts/batch/github_sync.bat index 159af7c..517bd9d 100644 --- a/scripts/batch/github_sync.bat +++ b/scripts/batch/github_sync.bat @@ -160,5 +160,10 @@ XCOPY "%cd%\Novetus\addons\Addon_Template.lua" "%dest%" /y XCOPY "%cd%\Novetus\addons\Utils.lua" "%dest%" /y XCOPY "%cd%\Novetus\addons\ShadersCompatibility.lua" "%dest%" /y XCOPY "%cd%\Novetus\addons\ServerWhitelist.lua" "%dest%" /y + XCOPY "%cd%\Novetus\addons\core\AddonLoader.lua" "%dest%" /y + +XCOPY "%cd%\Novetus\addons\novetusexts\webproxy\Asset.cs" "%dest%" /y +XCOPY "%cd%\Novetus\addons\novetusexts\webproxy\StudioLaunchPage.cs" "%dest%" /y +XCOPY "%cd%\Novetus\addons\novetusexts\webproxy\UploadWarnings.cs" "%dest%" /y if %debug%==1 pause \ No newline at end of file diff --git a/scripts/launcher/info.ini b/scripts/launcher/info.ini index ff02e34..e90a3fa 100644 --- a/scripts/launcher/info.ini +++ b/scripts/launcher/info.ini @@ -9,5 +9,5 @@ ExtendedVersionEditChangelog=True //ExtendedVersionTemplate=%version% v11.2022.%extended-revision%%lite% ExtendedVersionTemplate=%version% Snapshot v22.%build%.%revision%.%extended-revision% ExtendedVersionRevision=1 -InitialBootup=False +InitialBootup=True IsLite=False -- 2.40.1 From 4c98b40874ef3b6daf96e984c828c1404c21fb20 Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 6 Jan 2023 12:30:46 -0700 Subject: [PATCH 21/85] move addons to defaultaddons folder --- .../Addon_Template.lua | 0 .../ServerWhitelist.lua | 0 .../ShadersCompatibility.lua | 0 Utils.lua => defaultaddons/Utils.lua | 0 .../core/AddonLoader.lua | 0 .../novetusexts/webproxy/Asset.cs | 0 .../novetusexts/webproxy/StudioLaunchPage.cs | 0 .../novetusexts/webproxy/UploadWarnings.cs | 0 scripts/batch/github_sync.bat | 29 ++++++++++++------- 9 files changed, 18 insertions(+), 11 deletions(-) rename Addon_Template.lua => defaultaddons/Addon_Template.lua (100%) rename ServerWhitelist.lua => defaultaddons/ServerWhitelist.lua (100%) rename ShadersCompatibility.lua => defaultaddons/ShadersCompatibility.lua (100%) rename Utils.lua => defaultaddons/Utils.lua (100%) rename AddonLoader.lua => defaultaddons/core/AddonLoader.lua (100%) rename Asset.cs => defaultaddons/novetusexts/webproxy/Asset.cs (100%) rename StudioLaunchPage.cs => defaultaddons/novetusexts/webproxy/StudioLaunchPage.cs (100%) rename UploadWarnings.cs => defaultaddons/novetusexts/webproxy/UploadWarnings.cs (100%) diff --git a/Addon_Template.lua b/defaultaddons/Addon_Template.lua similarity index 100% rename from Addon_Template.lua rename to defaultaddons/Addon_Template.lua diff --git a/ServerWhitelist.lua b/defaultaddons/ServerWhitelist.lua similarity index 100% rename from ServerWhitelist.lua rename to defaultaddons/ServerWhitelist.lua diff --git a/ShadersCompatibility.lua b/defaultaddons/ShadersCompatibility.lua similarity index 100% rename from ShadersCompatibility.lua rename to defaultaddons/ShadersCompatibility.lua diff --git a/Utils.lua b/defaultaddons/Utils.lua similarity index 100% rename from Utils.lua rename to defaultaddons/Utils.lua diff --git a/AddonLoader.lua b/defaultaddons/core/AddonLoader.lua similarity index 100% rename from AddonLoader.lua rename to defaultaddons/core/AddonLoader.lua diff --git a/Asset.cs b/defaultaddons/novetusexts/webproxy/Asset.cs similarity index 100% rename from Asset.cs rename to defaultaddons/novetusexts/webproxy/Asset.cs diff --git a/StudioLaunchPage.cs b/defaultaddons/novetusexts/webproxy/StudioLaunchPage.cs similarity index 100% rename from StudioLaunchPage.cs rename to defaultaddons/novetusexts/webproxy/StudioLaunchPage.cs diff --git a/UploadWarnings.cs b/defaultaddons/novetusexts/webproxy/UploadWarnings.cs similarity index 100% rename from UploadWarnings.cs rename to defaultaddons/novetusexts/webproxy/UploadWarnings.cs diff --git a/scripts/batch/github_sync.bat b/scripts/batch/github_sync.bat index 517bd9d..52fb69f 100644 --- a/scripts/batch/github_sync.bat +++ b/scripts/batch/github_sync.bat @@ -1,6 +1,6 @@ @ECHO OFF -SET debug=0 +SET debug=1 SET basedir=%CD%\scripts SET gamescriptdir=%basedir%\game @@ -138,6 +138,23 @@ if not exist "%scriptsdir%" mkdir "%scriptsdir%" XCOPY /E "%basedir%" "%scriptsdir%" /sy rmdir "%basedir%" /s /q +echo. +echo Moving default addons and extensions... +SET addonsdir=%dest%\defaultaddons +if not exist "%addonsdir%" mkdir "%addonsdir%" +XCOPY "%cd%\Novetus\addons\*.lua" "%addonsdir%" /y + +SET addonscoredir=%addonsdir%\core +if not exist "%addonscoredir%" mkdir "%addonscoredir%" +XCOPY "%cd%\Novetus\addons\core\AddonLoader.lua" "%addonscoredir%" /y + +SET extfolder=%addonsdir%\novetusexts +if not exist "%extfolder%" mkdir "%extfolder%" + +SET extwebproxyfolder=%extfolder%\webproxy +if not exist "%extwebproxyfolder%" mkdir "%extwebproxyfolder%" +XCOPY "%cd%\Novetus\addons\novetusexts\webproxy\*.cs" "%extwebproxyfolder%" /sy + echo. echo Coying additional files to GitHub folder... if not exist "%dest%\scripts\batch" mkdir "%scriptsdir%\batch" @@ -156,14 +173,4 @@ XCOPY "%cd%\Novetus\changelog.txt" "%dest%\changelog.txt" /y XCOPY "%cd%\Novetus\LICENSE.txt" "%dest%\LICENSE" /y XCOPY "%cd%\Novetus\LICENSE-RESHADE.txt" "%dest%\LICENSE-RESHADE" /y XCOPY "%cd%\Novetus\README-AND-CREDITS.TXT" "%dest%" /y -XCOPY "%cd%\Novetus\addons\Addon_Template.lua" "%dest%" /y -XCOPY "%cd%\Novetus\addons\Utils.lua" "%dest%" /y -XCOPY "%cd%\Novetus\addons\ShadersCompatibility.lua" "%dest%" /y -XCOPY "%cd%\Novetus\addons\ServerWhitelist.lua" "%dest%" /y - -XCOPY "%cd%\Novetus\addons\core\AddonLoader.lua" "%dest%" /y - -XCOPY "%cd%\Novetus\addons\novetusexts\webproxy\Asset.cs" "%dest%" /y -XCOPY "%cd%\Novetus\addons\novetusexts\webproxy\StudioLaunchPage.cs" "%dest%" /y -XCOPY "%cd%\Novetus\addons\novetusexts\webproxy\UploadWarnings.cs" "%dest%" /y if %debug%==1 pause \ No newline at end of file -- 2.40.1 From abeece85dcc7595044c886dc24835a43cb559a87 Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 6 Jan 2023 15:56:26 -0700 Subject: [PATCH 22/85] web proxy changes. redesigned console --- Novetus/NovetusCore/Classes/WebProxy.cs | 12 +++++ .../StorageAndFunctions/NetFuncs.cs | 17 ++++++ .../Forms/LauncherForm/LauncherFormShared.cs | 2 +- .../Forms/NovetusConsole.Designer.cs | 36 ++++++++++++- .../NovetusLauncher/Forms/NovetusConsole.cs | 53 ++++++------------- Novetus/NovetusURI/Forms/LoaderForm.cs | 2 +- 6 files changed, 80 insertions(+), 42 deletions(-) diff --git a/Novetus/NovetusCore/Classes/WebProxy.cs b/Novetus/NovetusCore/Classes/WebProxy.cs index cbb8f05..86e7d9c 100644 --- a/Novetus/NovetusCore/Classes/WebProxy.cs +++ b/Novetus/NovetusCore/Classes/WebProxy.cs @@ -117,6 +117,12 @@ namespace Novetus.Core public void Start() { + if (Server.ProxyRunning) + { + Util.ConsolePrint("The web proxy is already on and running.", 2); + return; + } + try { LoadExtensions(); @@ -268,6 +274,12 @@ namespace Novetus.Core public void Stop() { + if (!Server.ProxyRunning) + { + Util.ConsolePrint("The web proxy is already turned off.", 2); + return; + } + Util.ConsolePrint("Web Proxy stopping on port " + GlobalVars.WebProxyPort, 3); Server.BeforeRequest -= new AsyncEventHandler(OnRequest); Server.Stop(); diff --git a/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs b/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs index 292ca75..f27dc3c 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs @@ -2,7 +2,9 @@ #region Usings using Mono.Nat; using System; +using System.Collections.Generic; using System.Web; +using Titanium.Web.Proxy.Models; #endregion namespace Novetus.Core @@ -61,6 +63,21 @@ namespace Novetus.Core { return HttpUtility.ParseQueryString(query)[searchQuery]; } + + public static IEnumerable GenerateHeaders(string content, string contenttype = "") + { + List HeaderList = new List(); + + if (!string.IsNullOrWhiteSpace(contenttype)) + { + HeaderList.Add(new HttpHeader("Content-Type", contenttype)); + } + + HeaderList.Add(new HttpHeader("Content-Length", content)); + HeaderList.Add(new HttpHeader("Cache-Control", "no-cache")); + + return HeaderList; + } } #endregion } diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs index 8ae7da9..1d615d8 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs @@ -189,7 +189,7 @@ namespace NovetusLauncher { DiscordRPC.Shutdown(); } - if (GlobalVars.Proxy.HasStarted()) + if (GlobalVars.UserConfiguration.WebProxyEnabled) { GlobalVars.Proxy.Stop(); } diff --git a/Novetus/NovetusLauncher/Forms/NovetusConsole.Designer.cs b/Novetus/NovetusLauncher/Forms/NovetusConsole.Designer.cs index 33e20c6..9307f83 100644 --- a/Novetus/NovetusLauncher/Forms/NovetusConsole.Designer.cs +++ b/Novetus/NovetusLauncher/Forms/NovetusConsole.Designer.cs @@ -30,6 +30,8 @@ { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NovetusConsole)); this.ConsoleBox = new System.Windows.Forms.RichTextBox(); + this.CommandBox = new System.Windows.Forms.TextBox(); + this.EnterButton = new System.Windows.Forms.Button(); this.SuspendLayout(); // // ConsoleBox @@ -43,16 +45,43 @@ this.ConsoleBox.ForeColor = System.Drawing.Color.White; this.ConsoleBox.Location = new System.Drawing.Point(0, 0); this.ConsoleBox.Name = "ConsoleBox"; - this.ConsoleBox.Size = new System.Drawing.Size(857, 411); + this.ConsoleBox.ReadOnly = true; + this.ConsoleBox.Size = new System.Drawing.Size(868, 389); this.ConsoleBox.TabIndex = 0; this.ConsoleBox.Text = ""; this.ConsoleBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ProcessConsole); // + // CommandBox + // + this.CommandBox.BackColor = System.Drawing.SystemColors.WindowText; + this.CommandBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.CommandBox.ForeColor = System.Drawing.Color.White; + this.CommandBox.Location = new System.Drawing.Point(3, 391); + this.CommandBox.Name = "CommandBox"; + this.CommandBox.Size = new System.Drawing.Size(783, 20); + this.CommandBox.TabIndex = 1; + // + // EnterButton + // + this.EnterButton.BackColor = System.Drawing.SystemColors.ControlText; + this.EnterButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.EnterButton.ForeColor = System.Drawing.Color.Lime; + this.EnterButton.Location = new System.Drawing.Point(789, 390); + this.EnterButton.Name = "EnterButton"; + this.EnterButton.Size = new System.Drawing.Size(75, 21); + this.EnterButton.TabIndex = 2; + this.EnterButton.Text = "Enter"; + this.EnterButton.UseVisualStyleBackColor = false; + this.EnterButton.Click += new System.EventHandler(this.EnterButton_Click); + // // NovetusConsole // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(858, 411); + this.BackColor = System.Drawing.SystemColors.ControlText; + this.ClientSize = new System.Drawing.Size(869, 415); + this.Controls.Add(this.EnterButton); + this.Controls.Add(this.CommandBox); this.Controls.Add(this.ConsoleBox); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MinimumSize = new System.Drawing.Size(357, 205); @@ -61,11 +90,14 @@ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ConsoleClose); this.Load += new System.EventHandler(this.NovetusConsole_Load); this.ResumeLayout(false); + this.PerformLayout(); } #endregion public System.Windows.Forms.RichTextBox ConsoleBox; + private System.Windows.Forms.TextBox CommandBox; + private System.Windows.Forms.Button EnterButton; } } \ No newline at end of file diff --git a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs index 1021212..29b7acd 100644 --- a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs +++ b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs @@ -222,6 +222,8 @@ namespace NovetusLauncher if (disableCommands) return; + CommandBox.Text = ""; + switch (cmd) { case string server when server.Contains("server", StringComparison.InvariantCultureIgnoreCase) == true: @@ -365,12 +367,6 @@ namespace NovetusLauncher if (vals[1].Equals("on", StringComparison.InvariantCultureIgnoreCase)) { - if (GlobalVars.Proxy.HasStarted()) - { - Util.ConsolePrint("The web proxy is already on and running.", 2); - return; - } - if (GlobalVars.UserConfiguration.WebProxyInitialSetupRequired) { // this is wierd and really dumb if we are just using console mode..... @@ -388,12 +384,6 @@ namespace NovetusLauncher } else if (vals[1].Equals("off", StringComparison.InvariantCultureIgnoreCase)) { - if (!GlobalVars.Proxy.HasStarted()) - { - Util.ConsolePrint("The web proxy is already turned off.", 2); - return; - } - if (!GlobalVars.UserConfiguration.WebProxyEnabled) { Util.ConsolePrint("The web proxy is disabled. Please turn it on in order to use this command.", 2); @@ -415,10 +405,7 @@ namespace NovetusLauncher GlobalVars.UserConfiguration.WebProxyEnabled = false; } - if (GlobalVars.Proxy.HasStarted()) - { - GlobalVars.Proxy.Stop(); - } + GlobalVars.Proxy.Stop(); Util.ConsolePrint("The web proxy has been disabled. To re-enable it, use the 'proxy on' command.", 2); } @@ -467,32 +454,22 @@ namespace NovetusLauncher return; } - //Command proxy - - int totalLines = ConsoleBox.Lines.Length; - if (totalLines > 0) + if (e.KeyCode == Keys.Enter) { - string lastLine = ConsoleBox.Lines[totalLines - 1]; + ConsoleProcessCommands(CommandBox.Text); + e.Handled = true; + } + } - if (e.KeyCode == Keys.Enter) - { - ConsoleProcessCommands(lastLine); - e.Handled = true; - } + private void EnterButton_Click(object sender, EventArgs e) + { + if (helpMode) + { + ConsoleForm.CloseEventInternal(); + return; } - if (e.Modifiers == Keys.Control) - { - switch (e.KeyCode) - { - case Keys.X: - case Keys.Z: - e.Handled = true; - break; - default: - break; - } - } + ConsoleProcessCommands(CommandBox.Text); } private void ClearConsole() diff --git a/Novetus/NovetusURI/Forms/LoaderForm.cs b/Novetus/NovetusURI/Forms/LoaderForm.cs index 29cba58..eb21161 100644 --- a/Novetus/NovetusURI/Forms/LoaderForm.cs +++ b/Novetus/NovetusURI/Forms/LoaderForm.cs @@ -109,7 +109,7 @@ namespace NovetusURI GlobalVars.GameOpened = ScriptType.None; } - if (GlobalVars.Proxy.HasStarted()) + if (GlobalVars.UserConfiguration.WebProxyEnabled) { GlobalVars.Proxy.Stop(); } -- 2.40.1 From 8fb827ab05646a5351f2aef2f88f147c5c66589c Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 6 Jan 2023 16:06:08 -0700 Subject: [PATCH 23/85] console changes --- Novetus/NovetusLauncher/Forms/NovetusConsole.Designer.cs | 5 +++++ Novetus/NovetusLauncher/Forms/NovetusConsole.cs | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Novetus/NovetusLauncher/Forms/NovetusConsole.Designer.cs b/Novetus/NovetusLauncher/Forms/NovetusConsole.Designer.cs index 9307f83..5fe7030 100644 --- a/Novetus/NovetusLauncher/Forms/NovetusConsole.Designer.cs +++ b/Novetus/NovetusLauncher/Forms/NovetusConsole.Designer.cs @@ -53,6 +53,8 @@ // // CommandBox // + this.CommandBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); this.CommandBox.BackColor = System.Drawing.SystemColors.WindowText; this.CommandBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.CommandBox.ForeColor = System.Drawing.Color.White; @@ -60,9 +62,11 @@ this.CommandBox.Name = "CommandBox"; this.CommandBox.Size = new System.Drawing.Size(783, 20); this.CommandBox.TabIndex = 1; + this.CommandBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ProcessConsole); // // EnterButton // + this.EnterButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.EnterButton.BackColor = System.Drawing.SystemColors.ControlText; this.EnterButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.EnterButton.ForeColor = System.Drawing.Color.Lime; @@ -73,6 +77,7 @@ this.EnterButton.Text = "Enter"; this.EnterButton.UseVisualStyleBackColor = false; this.EnterButton.Click += new System.EventHandler(this.EnterButton_Click); + this.EnterButton.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ProcessConsole); // // NovetusConsole // diff --git a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs index 29b7acd..cdc8bb6 100644 --- a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs +++ b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs @@ -476,7 +476,6 @@ namespace NovetusLauncher { ConsoleBox.Text = ""; ScrollToTop(); - Console.Clear(); } private void ScrollToTop() -- 2.40.1 From fc4730b721af1b80a7e16b18d928d5e56fa8d217 Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 6 Jan 2023 16:21:00 -0700 Subject: [PATCH 24/85] updated asset redirection script --- changelog.txt | 8 ++++++++ defaultaddons/novetusexts/webproxy/Asset.cs | 10 ++-------- scripts/batch/github_sync.bat | 2 +- scripts/launcher/info.ini | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/changelog.txt b/changelog.txt index c286554..858aeac 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,11 @@ +1.3 Snapshot v22.8406.29069.1 +Enhancements: +- Changed the design of the Console to be more user friendly. +- Further improved web proxy and Console reliability. + +Fixes: +- Fixed a bug involving cleraing the Console. +---------------------------------------------------------------------------- 1.3 Snapshot v22.8406.21589.1 Enhancements: - Added the following functionality to the Web Proxy: diff --git a/defaultaddons/novetusexts/webproxy/Asset.cs b/defaultaddons/novetusexts/webproxy/Asset.cs index ee8e3a8..e527c2b 100644 --- a/defaultaddons/novetusexts/webproxy/Asset.cs +++ b/defaultaddons/novetusexts/webproxy/Asset.cs @@ -27,7 +27,6 @@ public class Asset : IWebProxyExtension long id; if (!long.TryParse(NetFuncs.FindQueryString(query, "id"), out id)) { - Util.ConsolePrint(Name() + ": Redirecting " + query, 3); e.Redirect("https://assetdelivery.roblox.com/v1/asset/" + query); } else @@ -36,18 +35,13 @@ public class Asset : IWebProxyExtension if (PathList.Count > 0) { - Util.ConsolePrint(Name() + ": Local assets for " + id.ToString() + " found. Redirecting " + query, 3); + Util.ConsolePrint(Name() + ": Local asset for " + id.ToString() + " found. Using local asset.", 3); string First = PathList[0]; byte[] numArray = await Task.Run(() => File.ReadAllBytes(First)); - e.Ok(numArray, (IEnumerable) new List() - { - new HttpHeader("Content-Length", ((long) numArray.Length).ToString()), - new HttpHeader("Cache-Control", "no-cache") - }); + e.Ok(numArray, NetFuncs.GenerateHeaders(((long) numArray.Length).ToString())); } else { - Util.ConsolePrint(Name() + ": No local assets for " + id.ToString() + ". Redirecting " + query, 5); e.Redirect("https://assetdelivery.roblox.com/v1/asset/" + query); } } diff --git a/scripts/batch/github_sync.bat b/scripts/batch/github_sync.bat index 52fb69f..08530fa 100644 --- a/scripts/batch/github_sync.bat +++ b/scripts/batch/github_sync.bat @@ -1,6 +1,6 @@ @ECHO OFF -SET debug=1 +SET debug=0 SET basedir=%CD%\scripts SET gamescriptdir=%basedir%\game diff --git a/scripts/launcher/info.ini b/scripts/launcher/info.ini index e90a3fa..ff02e34 100644 --- a/scripts/launcher/info.ini +++ b/scripts/launcher/info.ini @@ -9,5 +9,5 @@ ExtendedVersionEditChangelog=True //ExtendedVersionTemplate=%version% v11.2022.%extended-revision%%lite% ExtendedVersionTemplate=%version% Snapshot v22.%build%.%revision%.%extended-revision% ExtendedVersionRevision=1 -InitialBootup=True +InitialBootup=False IsLite=False -- 2.40.1 From c3fa404daa67ddd56c4214204d150fc19528d4b8 Mon Sep 17 00:00:00 2001 From: Bitl Date: Sun, 8 Jan 2023 09:04:13 -0700 Subject: [PATCH 25/85] release new snapshot --- Novetus/NovetusCore/Classes/WebProxy.cs | 1 + .../StorageAndFunctions/FileManagement.cs | 2 +- changelog.txt | 4 ++-- scripts/launcher/splashes.txt | 13 ++++++++++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Novetus/NovetusCore/Classes/WebProxy.cs b/Novetus/NovetusCore/Classes/WebProxy.cs index 86e7d9c..483c153 100644 --- a/Novetus/NovetusCore/Classes/WebProxy.cs +++ b/Novetus/NovetusCore/Classes/WebProxy.cs @@ -283,6 +283,7 @@ namespace Novetus.Core Util.ConsolePrint("Web Proxy stopping on port " + GlobalVars.WebProxyPort, 3); Server.BeforeRequest -= new AsyncEventHandler(OnRequest); Server.Stop(); + Server.Dispose(); foreach (IWebProxyExtension extension in ExtensionList.ToArray()) { diff --git a/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs b/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs index 5561fab..14ae392 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs @@ -1335,7 +1335,7 @@ namespace Novetus.Core #if LAUNCHER public static void ResetConfigValues(Settings.Style style) #else - public static void ResetConfigValues() + public static void ResetConfigValues() #endif { bool WebProxySetupComplete = GlobalVars.UserConfiguration.WebProxyInitialSetupRequired; diff --git a/changelog.txt b/changelog.txt index 858aeac..8f5408a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,10 +1,10 @@ -1.3 Snapshot v22.8406.29069.1 +1.3 Snapshot v22.8408.16129.1 Enhancements: - Changed the design of the Console to be more user friendly. - Further improved web proxy and Console reliability. Fixes: -- Fixed a bug involving cleraing the Console. +- Fixed a bug involving clearing the Console. ---------------------------------------------------------------------------- 1.3 Snapshot v22.8406.21589.1 Enhancements: diff --git a/scripts/launcher/splashes.txt b/scripts/launcher/splashes.txt index 925cf35..73cc351 100644 --- a/scripts/launcher/splashes.txt +++ b/scripts/launcher/splashes.txt @@ -244,4 +244,15 @@ allows the user to use W... [normal]I'm the Toa of... of... Anarchy. [stylish]My name is... ah... Toa Vezon. I'm the Toa of... of... Anarchy. Your System ate a SPARC! Gah! -Dedicated to Missie. \ No newline at end of file +Dedicated to Missie. +novetus type beat +Requires AAA batteries! +Also try Sodikm! +Doesn't use leaked source code! +Gluten Free! +I've gotten to the mainframe! +A Guilty Pleasure! +Batteries not included. +Choose the pill! +Absolute dark power! +HELL IS FULL. -- 2.40.1 From 5b518175e9df8860d67d406191ea6cd7301483f1 Mon Sep 17 00:00:00 2001 From: Bitl Date: Wed, 11 Jan 2023 22:19:06 -0700 Subject: [PATCH 26/85] better extension management. --- Novetus/NovetusCore/Classes/Script.cs | 133 +++++++++++++++++- Novetus/NovetusCore/Classes/WebProxy.cs | 120 +++++++--------- .../NovetusLauncher/Forms/NovetusConsole.cs | 56 +++++++- 3 files changed, 233 insertions(+), 76 deletions(-) diff --git a/Novetus/NovetusCore/Classes/Script.cs b/Novetus/NovetusCore/Classes/Script.cs index e8069b2..f22b543 100644 --- a/Novetus/NovetusCore/Classes/Script.cs +++ b/Novetus/NovetusCore/Classes/Script.cs @@ -5,6 +5,7 @@ using Microsoft.CSharp; using System.CodeDom.Compiler; using System.IO; using System.Linq; +using System.Collections.Generic; #endregion // based on https://stackoverflow.com/questions/137933/what-is-the-best-scripting-language-to-embed-in-a-c-sharp-desktop-application @@ -15,12 +16,142 @@ namespace Novetus.Core { public virtual string Name() { return "Unnamed Object"; } public virtual string Version() { return "1.0.0"; } - public virtual string FullInfoString() { return (Name() + " v" + Version()); } + public virtual string Author() { return GlobalVars.UserConfiguration.PlayerName; } + public virtual string FullInfoString() { return (Name() + " v" + Version() + " by " + Author()); } public virtual void OnExtensionLoad() { } public virtual void OnExtensionUnload() { } } #endregion + #region ExtensionManager + public class ExtensionManager + { + private List ExtensionList = new List(); + private string directory = ""; + + public ExtensionManager() + { + } + + public virtual List GetExtensionList() + { + return ExtensionList; + } + + public virtual void LoadExtensions(string dirPath) + { + string nothingFoundError = "No extensions found."; + + if (!Directory.Exists(dirPath)) + { + Util.ConsolePrint(nothingFoundError, 5); + return; + } + else + { + directory = dirPath; + } + + // load up all .cs files. + string[] filePaths = Directory.GetFiles(dirPath, "*.cs", SearchOption.TopDirectoryOnly); + + if (filePaths.Count() == 0) + { + Util.ConsolePrint(nothingFoundError, 5); + return; + } + + foreach (string file in filePaths) + { + int index = 0; + + try + { + IExtension newExt = (IExtension)Script.LoadScriptFromContent(file); + ExtensionList.Add(newExt); + index = ExtensionList.IndexOf(newExt); + Util.ConsolePrint("Loaded extension " + newExt.FullInfoString() + " from " + Path.GetFileName(file), 3); + newExt.OnExtensionLoad(); + } + catch (Exception) + { + Util.ConsolePrint("Failed to load script " + Path.GetFileName(file), 2); + ExtensionList.RemoveAt(index); + continue; + } + } + } + + public virtual void ReloadExtensions() + { + string nothingFoundError = "No extensions found. There is nothing to reload."; + + if (!ExtensionList.Any()) + { + Util.ConsolePrint(nothingFoundError, 5); + return; + } + + Util.ConsolePrint("Reloading Extensions...", 2); + + UnloadExtensions(); + LoadExtensions(directory); + } + + public virtual void UnloadExtensions() + { + string nothingFoundError = "No extensions found. There is nothing to unload."; + + if (!ExtensionList.Any()) + { + Util.ConsolePrint(nothingFoundError, 5); + return; + } + + Util.ConsolePrint("Unloading all Extensions...", 2); + + foreach (IExtension extension in ExtensionList.ToArray()) + { + try + { + extension.OnExtensionUnload(); + } + catch (Exception) + { + } + } + + ExtensionList.Clear(); + } + + public virtual string GenerateExtensionList() + { + string nothingFoundError = "No extensions found."; + + if (!ExtensionList.Any()) + { + return nothingFoundError; + } + + string result = ""; + + foreach (IExtension extension in ExtensionList.ToArray()) + { + try + { + result += "- " + extension.FullInfoString() + "\n"; + } + catch (Exception) + { + } + } + + result.Trim(); + return result; + } + } + #endregion + #region Script public class Script { diff --git a/Novetus/NovetusCore/Classes/WebProxy.cs b/Novetus/NovetusCore/Classes/WebProxy.cs index 483c153..649b870 100644 --- a/Novetus/NovetusCore/Classes/WebProxy.cs +++ b/Novetus/NovetusCore/Classes/WebProxy.cs @@ -30,49 +30,9 @@ namespace Novetus.Core public class WebProxy { - private static List ExtensionList = new List(); - private static ProxyServer Server = new ProxyServer(); - private static ExplicitProxyEndPoint end; - - public void LoadExtensions() - { - string nothingFoundError = "No extensions found. The Web Proxy will run with limited functionality."; - - if (!Directory.Exists(GlobalPaths.NovetusExtsWebProxy)) - { - Util.ConsolePrint(nothingFoundError, 5); - return; - } - - // load up all .cs files. - string[] filePaths = Directory.GetFiles(GlobalPaths.NovetusExtsWebProxy, "*.cs", SearchOption.TopDirectoryOnly); - - if (filePaths.Count() == 0) - { - Util.ConsolePrint(nothingFoundError, 5); - return; - } - - foreach (string file in filePaths) - { - int index = 0; - - try - { - IWebProxyExtension newExt = (IWebProxyExtension)Script.LoadScriptFromContent(file); - ExtensionList.Add(newExt); - index = ExtensionList.IndexOf(newExt); - Util.ConsolePrint("Web Proxy: Loaded extension " + newExt.FullInfoString() + " from " + Path.GetFileName(file), 3); - newExt.OnExtensionLoad(); - } - catch (Exception) - { - Util.ConsolePrint("Web Proxy: Failed to load script " + Path.GetFileName(file), 2); - ExtensionList.RemoveAt(index); - continue; - } - } - } + private ProxyServer Server = null; + private ExplicitProxyEndPoint end; + public ExtensionManager Manager = new ExtensionManager(); public bool HasStarted() { @@ -117,6 +77,8 @@ namespace Novetus.Core public void Start() { + Server = new ProxyServer(); + if (Server.ProxyRunning) { Util.ConsolePrint("The web proxy is already on and running.", 2); @@ -125,7 +87,8 @@ namespace Novetus.Core try { - LoadExtensions(); + Manager.LoadExtensions(GlobalPaths.NovetusExtsWebProxy); + Util.ConsolePrint("Booting up Web Proxy...", 3); Server.CertificateManager.RootCertificateIssuerName = "Novetus"; Server.CertificateManager.RootCertificateName = "Novetus Web Proxy"; Server.BeforeRequest += new AsyncEventHandler(OnRequest); @@ -133,9 +96,13 @@ namespace Novetus.Core Util.ConsolePrint("Web Proxy started on port " + GlobalVars.WebProxyPort, 3); try { - foreach (IWebProxyExtension extension in ExtensionList.ToArray()) + foreach (IExtension extension in Manager.GetExtensionList().ToArray()) { - extension.OnProxyStart(); + IWebProxyExtension webProxyExtension = extension as IWebProxyExtension; + if (webProxyExtension != null) + { + webProxyExtension.OnProxyStart(); + } } } catch (Exception) @@ -218,22 +185,26 @@ namespace Novetus.Core Uri uri = e.HttpClient.Request.RequestUri; - foreach (IWebProxyExtension extension in ExtensionList.ToArray()) + foreach (IExtension extension in Manager.GetExtensionList().ToArray()) { - if (extension.IsValidURL(uri.AbsolutePath.ToLowerInvariant(), uri.Host)) + IWebProxyExtension webProxyExtension = extension as IWebProxyExtension; + if (webProxyExtension != null) { - try + if (webProxyExtension.IsValidURL(uri.AbsolutePath.ToLowerInvariant(), uri.Host)) { - await extension.OnBeforeTunnelConnectRequest(sender, e); + try + { + await webProxyExtension.OnBeforeTunnelConnectRequest(sender, e); + } + catch (Exception) + { + } } - catch (Exception) + else { + continue; } } - else - { - continue; - } } } @@ -248,25 +219,29 @@ namespace Novetus.Core Uri uri = e.HttpClient.Request.RequestUri; - foreach (IWebProxyExtension extension in ExtensionList.ToArray()) + foreach (IExtension extension in Manager.GetExtensionList().ToArray()) { - if (extension.IsValidURL(uri.AbsolutePath.ToLowerInvariant(), uri.Host)) + IWebProxyExtension webProxyExtension = extension as IWebProxyExtension; + if (webProxyExtension != null) { - try + if (webProxyExtension.IsValidURL(uri.AbsolutePath.ToLowerInvariant(), uri.Host)) { - await extension.OnRequest(sender, e); - return; + try + { + await webProxyExtension.OnRequest(sender, e); + return; + } + catch (Exception) + { + e.GenericResponse("", HttpStatusCode.InternalServerError); + continue; + } } - catch (Exception) + else { - e.GenericResponse("", HttpStatusCode.InternalServerError); continue; } } - else - { - continue; - } } e.GenericResponse("", HttpStatusCode.NotFound); @@ -284,20 +259,25 @@ namespace Novetus.Core Server.BeforeRequest -= new AsyncEventHandler(OnRequest); Server.Stop(); Server.Dispose(); + Server = null; - foreach (IWebProxyExtension extension in ExtensionList.ToArray()) + foreach (IExtension extension in Manager.GetExtensionList().ToArray()) { try { - extension.OnProxyStopped(); - extension.OnExtensionUnload(); + IWebProxyExtension webProxyExtension = extension as IWebProxyExtension; + if (webProxyExtension != null) + { + webProxyExtension.OnProxyStopped(); + } } catch (Exception) { } } - ExtensionList.Clear(); + Manager.UnloadExtensions(); + Manager.GetExtensionList().Clear(); } } } diff --git a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs index cdc8bb6..4a45dc1 100644 --- a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs +++ b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs @@ -224,6 +224,8 @@ namespace NovetusLauncher CommandBox.Text = ""; + Util.ConsolePrint("> " + cmd, 1, true); + switch (cmd) { case string server when server.Contains("server", StringComparison.InvariantCultureIgnoreCase) == true: @@ -248,12 +250,15 @@ namespace NovetusLauncher { ConsoleForm.StartGame(ScriptType.Server, false, false, true); } + ScrollToEnd(); break; case string client when string.Compare(client, "client", true, CultureInfo.InvariantCulture) == 0: ConsoleForm.StartGame(ScriptType.Client); + ScrollToEnd(); break; case string solo when string.Compare(solo, "solo", true, CultureInfo.InvariantCulture) == 0: ConsoleForm.StartGame(ScriptType.Solo); + ScrollToEnd(); break; case string studio when studio.Contains("studio", StringComparison.InvariantCultureIgnoreCase) == true: try @@ -277,6 +282,7 @@ namespace NovetusLauncher { ConsoleForm.StartGame(ScriptType.Studio, false, false, true); } + ScrollToEnd(); break; case string config when config.Contains("config", StringComparison.InvariantCultureIgnoreCase) == true: try @@ -304,15 +310,18 @@ namespace NovetusLauncher { Util.ConsolePrint("Please specify 'save', 'load', or 'reset'.", 2); } + ScrollToEnd(); break; case string help when string.Compare(help, "help", true, CultureInfo.InvariantCulture) == 0: ConsoleHelp(); break; case string documentation when string.Compare(documentation, "documentation", true, CultureInfo.InvariantCulture) == 0: ClientScriptDoc(); + ScrollToEnd(); break; case string sdk when string.Compare(sdk, "sdk", true, CultureInfo.InvariantCulture) == 0: ConsoleForm.LoadLauncher(); + ScrollToEnd(); break; case string dlldelete when string.Compare(dlldelete, "dlldelete", true, CultureInfo.InvariantCulture) == 0: if (GlobalVars.UserConfiguration.DisableReshadeDelete == true) @@ -325,6 +334,7 @@ namespace NovetusLauncher GlobalVars.UserConfiguration.DisableReshadeDelete = true; Util.ConsolePrint("ReShade DLL deletion disabled.", 4); } + ScrollToEnd(); break; case string altip when altip.Contains("altip", StringComparison.InvariantCultureIgnoreCase) == true: try @@ -346,6 +356,7 @@ namespace NovetusLauncher { Util.ConsolePrint("Please specify the IP address you would like to set Novetus to. Type 'none' to disable this.", 2); } + ScrollToEnd(); break; case string clear when clear.Contains("clear", StringComparison.InvariantCultureIgnoreCase) == true: ClearConsole(); @@ -354,11 +365,13 @@ namespace NovetusLauncher GlobalVars.AdminMode = true; Util.ConsolePrint("ADMIN MODE ENABLED.", 4); Util.ConsolePrint("YOU ARE GOD.", 2); + ScrollToEnd(); break; case string decode when (string.Compare(decode, "decode", true, CultureInfo.InvariantCulture) == 0 || string.Compare(decode, "decrypt", true, CultureInfo.InvariantCulture) == 0): + Util.ConsolePrint("???", 2); Decoder de = new Decoder(); de.Show(); - Util.ConsolePrint("???", 2); + ScrollToEnd(); break; case string proxy when proxy.Contains("proxy", StringComparison.InvariantCultureIgnoreCase) == true: try @@ -374,17 +387,18 @@ namespace NovetusLauncher } else { + // fast start it. if (!GlobalVars.UserConfiguration.WebProxyEnabled) { GlobalVars.UserConfiguration.WebProxyEnabled = true; } - } - GlobalVars.Proxy.Start(); + GlobalVars.Proxy.Start(); + } } else if (vals[1].Equals("off", StringComparison.InvariantCultureIgnoreCase)) { - if (!GlobalVars.UserConfiguration.WebProxyEnabled) + if (!GlobalVars.Proxy.HasStarted() && !GlobalVars.UserConfiguration.WebProxyEnabled) { Util.ConsolePrint("The web proxy is disabled. Please turn it on in order to use this command.", 2); return; @@ -409,6 +423,30 @@ namespace NovetusLauncher Util.ConsolePrint("The web proxy has been disabled. To re-enable it, use the 'proxy on' command.", 2); } + else if (vals[1].Equals("extensions", StringComparison.InvariantCultureIgnoreCase)) + { + if (!GlobalVars.Proxy.HasStarted() && !GlobalVars.UserConfiguration.WebProxyEnabled) + { + Util.ConsolePrint("The web proxy is disabled. Please turn it on in order to use this command.", 2); + return; + } + + try + { + if (vals[2].Equals("reload", StringComparison.InvariantCultureIgnoreCase)) + { + GlobalVars.Proxy.Manager.ReloadExtensions(); + } + else if (vals[2].Equals("list", StringComparison.InvariantCultureIgnoreCase)) + { + Util.ConsolePrintMultiLine(GlobalVars.Proxy.Manager.GenerateExtensionList(), 3); + } + } + catch (Exception) + { + Util.ConsolePrint("Please specify 'reload', or 'list'.", 2); + } + } else { Util.ConsolePrint("Please specify 'on', 'off', or 'disable'.", 2); @@ -416,11 +454,13 @@ namespace NovetusLauncher } catch (Exception) { - Util.ConsolePrint("Please specify 'on' or 'off', or 'disable'.", 2); + Util.ConsolePrint("Please specify 'on', 'off', or 'disable'.", 2); } + ScrollToEnd(); break; default: Util.ConsolePrint("Command is either not registered or valid", 2); + ScrollToEnd(); break; } } @@ -484,6 +524,12 @@ namespace NovetusLauncher ConsoleBox.ScrollToCaret(); } + private void ScrollToEnd() + { + ConsoleBox.SelectionStart = ConsoleBox.Text.Length; + ConsoleBox.ScrollToCaret(); + } + private void ConsoleClose(object sender, FormClosingEventArgs e) { CommandLineArguments.Arguments ConsoleArgs = new CommandLineArguments.Arguments(argList); -- 2.40.1 From a10dcdcdfa39dc52a88bb6fe35f3f634580abe2f Mon Sep 17 00:00:00 2001 From: Bitl Date: Thu, 12 Jan 2023 18:14:41 -0700 Subject: [PATCH 27/85] update to latest snapshot --- .../NovetusCore/Classes/SemaphoreLocker.cs | 37 + Novetus/NovetusCore/Classes/WebProxy.cs | 62 +- Novetus/NovetusCore/NovetusCore.projitems | 1 + .../StorageAndFunctions/ClientManagement.cs | 71 +- .../StorageAndFunctions/GlobalVars.cs | 3 +- .../StorageAndFunctions/SecurityFuncs.cs | 1 + .../NovetusCore/StorageAndFunctions/Util.cs | 18 +- .../Forms/LauncherForm/LauncherFormShared.cs | 26 +- .../NovetusLauncher/Forms/NovetusConsole.cs | 16 +- .../Forms/SDK/ItemCreationSDKColorMenu.cs | 2 - README-AND-CREDITS.TXT | 4 +- changelog.txt | 22 + consolehelp.txt | 4 +- defaultaddons/URLSetup.lua | 30 + defaultaddons/core/AddonLoader.lua | 2 +- defaultaddons/novetusexts/webproxy/Asset.cs | 5 + .../novetusexts/webproxy/AwardBadge.cs | 137 +++ .../novetusexts/webproxy/StudioLaunchPage.cs | 5 + .../novetusexts/webproxy/UploadWarnings.cs | 5 + scripts/batch/clean_junk.bat | 1 + scripts/launcher/Appreciation.rbxl | 962 +++++++++--------- 21 files changed, 826 insertions(+), 588 deletions(-) create mode 100644 Novetus/NovetusCore/Classes/SemaphoreLocker.cs create mode 100644 defaultaddons/URLSetup.lua create mode 100644 defaultaddons/novetusexts/webproxy/AwardBadge.cs diff --git a/Novetus/NovetusCore/Classes/SemaphoreLocker.cs b/Novetus/NovetusCore/Classes/SemaphoreLocker.cs new file mode 100644 index 0000000..71837d1 --- /dev/null +++ b/Novetus/NovetusCore/Classes/SemaphoreLocker.cs @@ -0,0 +1,37 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +//https://stackoverflow.com/questions/7612602/why-cant-i-use-the-await-operator-within-the-body-of-a-lock-statement/50139704#50139704 + +public class SemaphoreLocker +{ + private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); + + public async Task LockAsync(Func worker) + { + await _semaphore.WaitAsync(); + try + { + await worker(); + } + finally + { + _semaphore.Release(); + } + } + + // overloading variant for non-void methods with return type (generic T) + public async Task LockAsync(Func> worker) + { + await _semaphore.WaitAsync(); + try + { + return await worker(); + } + finally + { + _semaphore.Release(); + } + } +} \ No newline at end of file diff --git a/Novetus/NovetusCore/Classes/WebProxy.cs b/Novetus/NovetusCore/Classes/WebProxy.cs index 649b870..0e95d08 100644 --- a/Novetus/NovetusCore/Classes/WebProxy.cs +++ b/Novetus/NovetusCore/Classes/WebProxy.cs @@ -30,14 +30,11 @@ namespace Novetus.Core public class WebProxy { - private ProxyServer Server = null; + private ProxyServer Server = new ProxyServer(); private ExplicitProxyEndPoint end; public ExtensionManager Manager = new ExtensionManager(); - - public bool HasStarted() - { - return Server.ProxyRunning; - } + private static readonly SemaphoreLocker _locker = new SemaphoreLocker(); + public bool Started { get { return Server.ProxyRunning; } } public void DoSetup() { @@ -77,8 +74,6 @@ namespace Novetus.Core public void Start() { - Server = new ProxyServer(); - if (Server.ProxyRunning) { Util.ConsolePrint("The web proxy is already on and running.", 2); @@ -208,43 +203,44 @@ namespace Novetus.Core } } -#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously private async Task OnRequest(object sender, SessionEventArgs e) -#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously { - if (!IsValidURL(e.HttpClient)) + await _locker.LockAsync(async () => { - return; - } - - Uri uri = e.HttpClient.Request.RequestUri; - - foreach (IExtension extension in Manager.GetExtensionList().ToArray()) - { - IWebProxyExtension webProxyExtension = extension as IWebProxyExtension; - if (webProxyExtension != null) + if (!IsValidURL(e.HttpClient)) { - if (webProxyExtension.IsValidURL(uri.AbsolutePath.ToLowerInvariant(), uri.Host)) + return; + } + + Uri uri = e.HttpClient.Request.RequestUri; + + foreach (IExtension extension in Manager.GetExtensionList().ToArray()) + { + IWebProxyExtension webProxyExtension = extension as IWebProxyExtension; + if (webProxyExtension != null) { - try + if (webProxyExtension.IsValidURL(uri.AbsolutePath.ToLowerInvariant(), uri.Host)) { - await webProxyExtension.OnRequest(sender, e); - return; + try + { + await webProxyExtension.OnRequest(sender, e); + return; + } + catch (Exception) + { + e.GenericResponse("", HttpStatusCode.InternalServerError); + continue; + } } - catch (Exception) + else { - e.GenericResponse("", HttpStatusCode.InternalServerError); continue; } } - else - { - continue; - } } - } - e.GenericResponse("", HttpStatusCode.NotFound); + e.GenericResponse("", HttpStatusCode.NotFound); + }); } public void Stop() @@ -258,8 +254,6 @@ namespace Novetus.Core Util.ConsolePrint("Web Proxy stopping on port " + GlobalVars.WebProxyPort, 3); Server.BeforeRequest -= new AsyncEventHandler(OnRequest); Server.Stop(); - Server.Dispose(); - Server = null; foreach (IExtension extension in Manager.GetExtensionList().ToArray()) { diff --git a/Novetus/NovetusCore/NovetusCore.projitems b/Novetus/NovetusCore/NovetusCore.projitems index 2563963..658dacc 100644 --- a/Novetus/NovetusCore/NovetusCore.projitems +++ b/Novetus/NovetusCore/NovetusCore.projitems @@ -10,6 +10,7 @@ + diff --git a/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs b/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs index edd96bd..cad8171 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs @@ -335,6 +335,7 @@ namespace Novetus.Core case ScriptType.Studio: return GlobalVars.LauncherState.InStudio; case ScriptType.EasterEgg: + case ScriptType.EasterEggServer: return GlobalVars.LauncherState.InEasterEggGame; default: return GlobalVars.LauncherState.InLauncher; @@ -893,6 +894,7 @@ namespace Novetus.Core rbxfolder = "client"; break; case ScriptType.Server: + case ScriptType.EasterEggServer: rbxfolder = "server"; break; case ScriptType.Studio: @@ -929,11 +931,14 @@ namespace Novetus.Core switch (type) { case ScriptType.Client: - case ScriptType.Solo: case ScriptType.EasterEgg: rbxexe = BasePath + @"\\" + GetClientSeperateFolderName(type) + @"\\RobloxApp_client.exe"; break; + case ScriptType.Solo: + rbxexe = BasePath + @"\\" + GetClientSeperateFolderName(type) + @"\\RobloxApp_solo.exe"; + break; case ScriptType.Server: + case ScriptType.EasterEggServer: rbxexe = BasePath + @"\\" + GetClientSeperateFolderName(type) + @"\\RobloxApp_server.exe"; break; case ScriptType.Studio: @@ -950,16 +955,17 @@ namespace Novetus.Core switch (type) { case ScriptType.Client: + case ScriptType.EasterEgg: rbxexe = BasePath + @"\\RobloxApp_client.exe"; break; case ScriptType.Server: + case ScriptType.EasterEggServer: rbxexe = BasePath + @"\\RobloxApp_server.exe"; break; case ScriptType.Studio: rbxexe = BasePath + @"\\RobloxApp_studio.exe"; break; case ScriptType.Solo: - case ScriptType.EasterEgg: rbxexe = BasePath + @"\\RobloxApp_solo.exe"; break; case ScriptType.None: @@ -1045,7 +1051,7 @@ namespace Novetus.Core #if URI UpdateStatus(label, "The client has been detected as modified."); #elif LAUNCHER - Util.ConsolePrint("ERROR - Failed to launch Novetus. (The client has been detected as modified.)", 2); + Util.ConsolePrint("ERROR - Failed to launch Novetus. (The client has been detected as modified.)", 2); #endif #if LAUNCHER @@ -1075,46 +1081,48 @@ namespace Novetus.Core #endif { #if LAUNCHER - DecompressMap(type, nomap); + DecompressMap(type, nomap); #endif switch (type) { case ScriptType.Client: + case ScriptType.EasterEgg: FileManagement.ReloadLoadoutValue(true); - if (!GlobalVars.LocalPlayMode && GlobalVars.GameOpened != ScriptType.Server) + if (!GlobalVars.LocalPlayMode && GlobalVars.GameOpened != ScriptType.Server && GlobalVars.GameOpened != ScriptType.EasterEggServer) { goto default; } break; case ScriptType.Server: - if (GlobalVars.GameOpened == ScriptType.Server) + case ScriptType.EasterEggServer: + if (GlobalVars.GameOpened == ScriptType.Server || GlobalVars.GameOpened == ScriptType.EasterEggServer) { Util.ConsolePrint("ERROR - Failed to launch Novetus. (A server is already running.)", 2); #if LAUNCHER - if (!GlobalVars.isConsoleOnly) - { - MessageBox.Show("Failed to launch Novetus. (Error: A server is already running.)", "Novetus - Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } + if (!GlobalVars.isConsoleOnly) + { + MessageBox.Show("Failed to launch Novetus. (Error: A server is already running.)", "Novetus - Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } #endif return; } - else if (GlobalVars.UserConfiguration.FirstServerLaunch) + else if (GlobalVars.UserConfiguration.FirstServerLaunch && GlobalVars.GameOpened == ScriptType.Server) { #if LAUNCHER - string hostingTips = "For your first time hosting a server, make sure your server's port forwarded (set up in your router), going through a tunnel server, or running from UPnP.\n" + - "If your port is forwarded or you are going through a tunnel server, make sure your port is set up as UDP, not TCP.\n" + - "Roblox does NOT use TCP, only UDP. However, if your server doesn't work with just UDP, feel free to set up TCP too as that might help the issue in some cases."; + string hostingTips = "For your first time hosting a server, make sure your server's port forwarded (set up in your router), going through a tunnel server, or running from UPnP.\n" + + "If your port is forwarded or you are going through a tunnel server, make sure your port is set up as UDP, not TCP.\n" + + "Roblox does NOT use TCP, only UDP. However, if your server doesn't work with just UDP, feel free to set up TCP too as that might help the issue in some cases."; - if (!GlobalVars.isConsoleOnly) - { - MessageBox.Show(hostingTips, "Novetus - Hosting Tips", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - else - { - Util.ConsolePrint("Tips: " + hostingTips, 4); - } + if (!GlobalVars.isConsoleOnly) + { + MessageBox.Show(hostingTips, "Novetus - Hosting Tips", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + Util.ConsolePrint("Tips: " + hostingTips, 4); + } #endif GlobalVars.UserConfiguration.FirstServerLaunch = false; } @@ -1132,10 +1140,10 @@ namespace Novetus.Core Util.ConsolePrint("ERROR - Failed to launch Novetus. (A game is already running.)", 2); #if LAUNCHER - if (!GlobalVars.isConsoleOnly) - { - MessageBox.Show("Failed to launch Novetus. (Error: A game is already running.)", "Novetus - Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } + if (!GlobalVars.isConsoleOnly) + { + MessageBox.Show("Failed to launch Novetus. (Error: A game is already running.)", "Novetus - Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } #endif return; } @@ -1145,10 +1153,9 @@ namespace Novetus.Core ReadClientValues(ClientName); string luafile = GetLuaFileName(ClientName, type); string rbxexe = GetClientEXEDir(ClientName, type); - string mapfile = type.Equals(ScriptType.EasterEgg) ? - GlobalPaths.DataDir + "\\Appreciation.rbxl" : - (nomap ? (type.Equals(ScriptType.Studio) ? GlobalPaths.ConfigDir + "\\Place1.rbxl" : "") : GlobalVars.UserConfiguration.MapPath); - string mapname = type.Equals(ScriptType.EasterEgg) ? "" : (nomap ? "" : GlobalVars.UserConfiguration.Map); + bool isEasterEgg = (type.Equals(ScriptType.EasterEggServer)); + string mapfile = isEasterEgg ? GlobalPaths.DataDir + "\\Appreciation.rbxl" : (nomap ? (type.Equals(ScriptType.Studio) ? GlobalPaths.ConfigDir + "\\Place1.rbxl" : "") : GlobalVars.UserConfiguration.MapPath); + string mapname = isEasterEgg ? "" : (nomap ? "" : GlobalVars.UserConfiguration.Map); FileFormat.ClientInfo info = GetClientInfoValues(ClientName); string quote = "\""; string args = ""; @@ -1488,6 +1495,7 @@ namespace Novetus.Core switch (type) { case ScriptType.Client: + case ScriptType.EasterEgg: return "_G.CSConnect(" + (info.UsesID ? GlobalVars.UserConfiguration.UserID : 0) + ",'" + GlobalVars.CurrentServer.ServerIP + "'," @@ -1499,6 +1507,7 @@ namespace Novetus.Core + ((GlobalVars.ValidatedExtraFiles > 0) ? "'," + GlobalVars.ValidatedExtraFiles.ToString() + "," : "',0,") + GlobalVars.UserConfiguration.NewGUI.ToString().ToLower() + ");"; case ScriptType.Server: + case ScriptType.EasterEggServer: return "_G.CSServer(" + GlobalVars.UserConfiguration.RobloxPort + "," + GlobalVars.UserConfiguration.PlayerLimit + "," @@ -1507,7 +1516,6 @@ namespace Novetus.Core + ((GlobalVars.ValidatedExtraFiles > 0) ? "," + GlobalVars.ValidatedExtraFiles.ToString() + "," : ",0,") + GlobalVars.UserConfiguration.NewGUI.ToString().ToLower() + ");"; case ScriptType.Solo: - case ScriptType.EasterEgg: return "_G.CSSolo(" + (info.UsesID ? GlobalVars.UserConfiguration.UserID : 0) + ",'" + (info.UsesPlayerName ? GlobalVars.UserConfiguration.PlayerName : "Player") + "'," @@ -1534,6 +1542,7 @@ namespace Novetus.Core case ScriptType.Studio: return "Studio"; case ScriptType.EasterEgg: + case ScriptType.EasterEggServer: return "A message from Bitl"; default: return "N/A"; diff --git a/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs b/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs index 1f7d1dd..8465a11 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs @@ -24,7 +24,8 @@ namespace Novetus.Core Solo = 2, Studio = 3, EasterEgg = 4, - None = 5 + EasterEggServer = 5, + None = 6 } #endregion diff --git a/Novetus/NovetusCore/StorageAndFunctions/SecurityFuncs.cs b/Novetus/NovetusCore/StorageAndFunctions/SecurityFuncs.cs index 0fe29f2..7d1772c 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/SecurityFuncs.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/SecurityFuncs.cs @@ -299,6 +299,7 @@ namespace Novetus.Core + RandomStringTitle()); break; case ScriptType.EasterEgg: + case ScriptType.EasterEggServer: default: SetWindowText(exe.MainWindowHandle, ScriptFuncs.Generator.GetNameForType(type) + RandomStringTitle()); diff --git a/Novetus/NovetusCore/StorageAndFunctions/Util.cs b/Novetus/NovetusCore/StorageAndFunctions/Util.cs index 3ba1ef1..6cce83e 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/Util.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/Util.cs @@ -680,7 +680,7 @@ namespace Novetus.Core return (p <= 0); } - public static void ConsolePrint(string text, int type = 1, bool noLog = false) + public static void ConsolePrint(string text, int type = 1, bool noLog = false, bool scrollDown = true) { switch (type) { @@ -718,7 +718,7 @@ namespace Novetus.Core #if LAUNCHER if (GlobalVars.consoleForm != null) { - FormPrint(text, type, GlobalVars.consoleForm.ConsoleBox); + FormPrint(text, type, GlobalVars.consoleForm.ConsoleBox, scrollDown); } #endif } @@ -756,7 +756,7 @@ namespace Novetus.Core } } - private static void FormPrint(string text, int type, RichTextBox box) + private static void FormPrint(string text, int type, RichTextBox box, bool scrollDown = true) { if (box == null) return; @@ -790,6 +790,12 @@ namespace Novetus.Core box.AppendText(text, Color.Black); break; } + + if (scrollDown) + { + box.SelectionStart = box.Text.Length; + box.ScrollToCaret(); + } } private static void ConsoleText(string text, ConsoleColor color, bool newLine = false) @@ -805,7 +811,7 @@ namespace Novetus.Core } } - public static void ReadTextFileWithColor(string path) + public static void ReadTextFileWithColor(string path, bool scrollDown = true) { var lines = File.ReadLines(path); foreach (var line in lines) @@ -813,11 +819,11 @@ namespace Novetus.Core try { string[] vals = line.Split('|'); - ConsolePrint(vals[0], Convert.ToInt32(vals[1]), true); + ConsolePrint(vals[0], Convert.ToInt32(vals[1]), true, scrollDown); } catch (Exception) { - ConsolePrint(line, 1, true); + ConsolePrint(line, 1, true, scrollDown); } } } diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs index 1d615d8..d0093c9 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs @@ -142,6 +142,7 @@ namespace NovetusLauncher switch (GlobalVars.GameOpened) { case ScriptType.Server: + case ScriptType.EasterEggServer: ShowCloseError("A server is open.", "Server", e); break; default: @@ -191,7 +192,13 @@ namespace NovetusLauncher } if (GlobalVars.UserConfiguration.WebProxyEnabled) { - GlobalVars.Proxy.Stop(); + try + { + GlobalVars.Proxy.Stop(); + } + catch + { + } } if (!GlobalVars.AppClosed) @@ -269,7 +276,7 @@ namespace NovetusLauncher } } - public void StartGame(ScriptType gameType, bool no3d = false, bool nomap = false, bool console = false) + public async void StartGame(ScriptType gameType, bool no3d = false, bool nomap = false, bool console = false) { if (!console) { @@ -355,7 +362,9 @@ namespace NovetusLauncher ClientManagement.LaunchRBXClient(ScriptType.Studio, false, nomap, new EventHandler(ClientExitedBase)); break; case ScriptType.EasterEgg: - ClientManagement.LaunchRBXClient(ScriptType.EasterEgg, false, false, new EventHandler(EasterEggExited)); + ClientManagement.LaunchRBXClient(ScriptType.EasterEggServer, false, false, new EventHandler(ServerExited)); + await Util.Delay(1500); + ClientManagement.LaunchRBXClient(ScriptType.EasterEgg, false, true, new EventHandler(EasterEggExited)); break; case ScriptType.None: default: @@ -370,6 +379,11 @@ namespace NovetusLauncher public void EasterEggLogic() { + if (LocalVars.Clicks <= 0) + { + LocalVars.prevsplash = SplashLabel.Text; + } + if (LocalVars.Clicks < 10) { LocalVars.Clicks += 1; @@ -431,6 +445,12 @@ namespace NovetusLauncher { LocalVars.Clicks = 0; } + + var processes = Process.GetProcessesByName("RobloxApp_server"); + foreach (var process in processes) + { + process.Kill(); + } ClientExitedBase(sender, e); } diff --git a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs index 4a45dc1..7083114 100644 --- a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs +++ b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs @@ -398,7 +398,7 @@ namespace NovetusLauncher } else if (vals[1].Equals("off", StringComparison.InvariantCultureIgnoreCase)) { - if (!GlobalVars.Proxy.HasStarted() && !GlobalVars.UserConfiguration.WebProxyEnabled) + if (!GlobalVars.Proxy.Started && !GlobalVars.UserConfiguration.WebProxyEnabled) { Util.ConsolePrint("The web proxy is disabled. Please turn it on in order to use this command.", 2); return; @@ -408,7 +408,7 @@ namespace NovetusLauncher } else if (vals[1].Equals("disable", StringComparison.InvariantCultureIgnoreCase)) { - if (!GlobalVars.Proxy.HasStarted() && !GlobalVars.UserConfiguration.WebProxyEnabled) + if (!GlobalVars.Proxy.Started && !GlobalVars.UserConfiguration.WebProxyEnabled) { Util.ConsolePrint("The web proxy is already disabled.", 2); return; @@ -425,7 +425,7 @@ namespace NovetusLauncher } else if (vals[1].Equals("extensions", StringComparison.InvariantCultureIgnoreCase)) { - if (!GlobalVars.Proxy.HasStarted() && !GlobalVars.UserConfiguration.WebProxyEnabled) + if (!GlobalVars.Proxy.Started && !GlobalVars.UserConfiguration.WebProxyEnabled) { Util.ConsolePrint("The web proxy is disabled. Please turn it on in order to use this command.", 2); return; @@ -468,9 +468,9 @@ namespace NovetusLauncher public void ConsoleHelp() { ClearConsole(); - Util.ConsolePrint("Help:", 3, true); - Util.ReadTextFileWithColor(GlobalPaths.BasePath + "\\" + GlobalPaths.ConsoleHelpFileName); - Util.ConsolePrint(GlobalVars.Important2, 0, true); + Util.ConsolePrint("Help:", 3, true, false); + Util.ReadTextFileWithColor(GlobalPaths.BasePath + "\\" + GlobalPaths.ConsoleHelpFileName, false); + Util.ConsolePrint(GlobalVars.Important2, 0, true, false); ScrollToTop(); } @@ -478,7 +478,7 @@ namespace NovetusLauncher { ClearConsole(); Util.ConsolePrint("ClientScript Documentation:", 3, true); - Util.ReadTextFileWithColor(GlobalPaths.BasePath + "\\" + GlobalPaths.ClientScriptDocumentationFileName); + Util.ReadTextFileWithColor(GlobalPaths.BasePath + "\\" + GlobalPaths.ClientScriptDocumentationFileName, false); ScrollToTop(); } @@ -537,7 +537,7 @@ namespace NovetusLauncher { GlobalVars.UserConfiguration = savedConfig; } - ConsoleForm.CloseEventInternal(); + ConsoleForm.CloseEvent(e); } } } diff --git a/Novetus/NovetusLauncher/Forms/SDK/ItemCreationSDKColorMenu.cs b/Novetus/NovetusLauncher/Forms/SDK/ItemCreationSDKColorMenu.cs index 2e03d2f..970f9d0 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/ItemCreationSDKColorMenu.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/ItemCreationSDKColorMenu.cs @@ -35,9 +35,7 @@ public partial class ItemCreationSDKColorMenu : Form } parent.partColorID = Convert.ToInt32(colorMenu.Items[selectedIndex].Tag); -#pragma warning disable CS1690 // Accessing a member on a field of a marshal-by-reference class may cause a runtime exception parent.partColorLabel.Text = parent.partColorID.ToString(); -#pragma warning restore CS1690 // Accessing a member on a field of a marshal-by-reference class may cause a runtime exception Close(); } diff --git a/README-AND-CREDITS.TXT b/README-AND-CREDITS.TXT index 4be084b..7d74297 100644 --- a/README-AND-CREDITS.TXT +++ b/README-AND-CREDITS.TXT @@ -306,10 +306,10 @@ ROBLOX Script Generator was made by S. Costeira. Thank you to NT_x86 for helping me with security fixes. Thank you XlXi for the idea of the original logo. This logo was remade in newer verions in higher quality. Thank you Nukley for the idea of the Splash Tester. -Credits go to Nostal-ia for getting 2011M corescripts working and helping me with 2011E corescripts. +Credits go to matboff for getting 2011M corescripts working and helping me with 2011E corescripts. Credits to Hazelnut (creator of JRBX) for the buttons used in the Stylish style. Credits go to davcs86 for the HWID generation code (https://github.com/davcs86/csharp-uhwid) -Credits go to BRAVONATCHO and Sodikm for parts of the web proxy code. +Credits go to matboff and Sodikm for parts of the web proxy code. All credits for the used pieces of code go to the respective authors. ------------------------------------------------------------ diff --git a/changelog.txt b/changelog.txt index 8f5408a..04cc096 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,25 @@ +1.3 Snapshot v22.8412.32591.1 +Enhancements: +- Added badge support to the Web Proxy. +- The Easter Egg now loads up a server and a client, rather than loading a client in Play Solo mode. +- Further improved web proxy reliability. + +Fixes: +- Fixed the previous splash not showing up after closing the Easter Egg. +- Fixed a bug where the Console could close Novetus with a client open. +---------------------------------------------------------------------------- +1.3 Snapshot v22.8411.39962.1 +Enhancements: +- Web Proxy Extension API additions: + - Added Author(). +- Improved Web Proxy Extension loading and management. +- Improved the Console user experience. +- Added proxy extensions reload - Reloads all Web Proxy extensions. +- Added proxy extensions list - Lists all Web Proxy extensions. + +Fixes: +- Fixed a bug that happens when the user manually stops the Web Proxy with the Console. +---------------------------------------------------------------------------- 1.3 Snapshot v22.8408.16129.1 Enhancements: - Changed the design of the Console to be more user friendly. diff --git a/consolehelp.txt b/consolehelp.txt index b9f8b7d..f2adc74 100644 --- a/consolehelp.txt +++ b/consolehelp.txt @@ -16,7 +16,9 @@ Commands:|3 + config save - Saves the config file|4 + config load - Reloads the config file|4 + config reset - Resets the config file|4 -+ proxy - Turns Novetus' web proxy on and off. ++ proxy - Turns Novetus' web proxy on and off. 'disable' disables the web proxy entirely.|4 ++ proxy extensions reload - Reloads all Web Proxy extensions.|4 ++ proxy extensions list - Lists all Web Proxy extensions.|4 ---------|1 Command-Line Parameters:|3 ---------|1 diff --git a/defaultaddons/URLSetup.lua b/defaultaddons/URLSetup.lua new file mode 100644 index 0000000..e45f5c6 --- /dev/null +++ b/defaultaddons/URLSetup.lua @@ -0,0 +1,30 @@ +local this = {} + +function this:Name() + return "URL Setup Addon" +end + +function this:IsEnabled(Script, Client) + if (Script ~= "Studio") then + return true + else + return false + end +end + +function this:PreInit(Script, Client) + pcall(function() game:GetService("BadgeService"):SetPlaceId(game.PlaceId) end) + pcall(function() game:GetService("BadgeService"):SetAwardBadgeUrl("http://www.roblox.com/Game/Badge/AwardBadge.ashx?UserID=%d&BadgeID=%d&PlaceID=%d") end) + pcall(function() game:GetService("BadgeService"):SetHasBadgeUrl("http://www.roblox.com/Game/Badge/HasBadge.ashx?UserID=%d&BadgeID=%d") end) + pcall(function() game:GetService("BadgeService"):SetIsBadgeDisabledUrl("http://www.roblox.com/Game/Badge/IsBadgeDisabled.ashx?BadgeID=%d&PlaceID=%d") end) + pcall(function() game:GetService("BadgeService"):SetIsBadgeLegalUrl("") end) +end + +-- DO NOT REMOVE THIS. this is required to load this addon into the game. + +function AddModule(t) + print("AddonLoader: Adding " .. this:Name()) + table.insert(t, this) +end + +_G.CSScript_AddModule=AddModule \ No newline at end of file diff --git a/defaultaddons/core/AddonLoader.lua b/defaultaddons/core/AddonLoader.lua index e3743dc..2bb83b8 100644 --- a/defaultaddons/core/AddonLoader.lua +++ b/defaultaddons/core/AddonLoader.lua @@ -1,6 +1,6 @@ -- put script names here -Addons = {"Utils", "ShadersCompatibility", "ServerWhitelist"} +Addons = {"Utils", "ShadersCompatibility", "ServerWhitelist", "URLSetup"} -- DONT EDIT ANYTHING ELSE BELOW diff --git a/defaultaddons/novetusexts/webproxy/Asset.cs b/defaultaddons/novetusexts/webproxy/Asset.cs index e527c2b..7c21e82 100644 --- a/defaultaddons/novetusexts/webproxy/Asset.cs +++ b/defaultaddons/novetusexts/webproxy/Asset.cs @@ -16,6 +16,11 @@ public class Asset : IWebProxyExtension return "Asset Redirection Extension"; } + public override string Author() + { + return "Bitl"; + } + public override bool IsValidURL(string absolutePath, string host) { return (absolutePath.EndsWith("/asset") || absolutePath.EndsWith("/asset/")); diff --git a/defaultaddons/novetusexts/webproxy/AwardBadge.cs b/defaultaddons/novetusexts/webproxy/AwardBadge.cs new file mode 100644 index 0000000..d8e498e --- /dev/null +++ b/defaultaddons/novetusexts/webproxy/AwardBadge.cs @@ -0,0 +1,137 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using System.Web; +using System.Net; +using System.Collections.Generic; +using Titanium.Web.Proxy; +using Titanium.Web.Proxy.EventArguments; +using Titanium.Web.Proxy.Http; +using Titanium.Web.Proxy.Models; +using Novetus.Core; + +public class AwardBadge : IWebProxyExtension +{ + struct BadgeData + { + public long BadgeId; + public string BadgeName; + public string BadgeCreatorName; + } + + private static readonly string BadgeDatabasePath = GlobalPaths.ConfigDir + "\\BadgeDatabase.ini"; + private string BadgeDatabaseSection = "BadgeDatabase"; + private string MetadataFileExtension = "_meta.ini"; + private INIFile ini = new INIFile(BadgeDatabasePath); + + public override string Name() + { + return "Badge Award Extension"; + } + + public override string Author() + { + return "Bitl"; + } + + void AddBadgeToDB(long BadgeID, bool Awarded = false) + { + CreateBadgeDatabaseIfNeeded(); + ini.IniWriteValue(BadgeDatabaseSection, BadgeID.ToString(), Awarded.ToString()); + } + + bool PlayerHasBadge(long BadgeID) + { + CreateBadgeDatabaseIfNeeded(); + + if (ini.IniValueExists(BadgeID.ToString())) + { + string awarded = ini.IniReadValue(BadgeDatabaseSection, BadgeID.ToString(), "False"); + return Convert.ToBoolean(awarded); + } + + return false; + } + + void CreateBadgeDatabaseIfNeeded() + { + if (!File.Exists(BadgeDatabasePath)) + { + Util.ConsolePrint("WARNING - " + BadgeDatabasePath + " not found. Creating empty badge database.", 5); + File.Create(BadgeDatabasePath).Dispose(); + } + } + + public override void OnExtensionLoad() + { + CreateBadgeDatabaseIfNeeded(); + } + + BadgeData LoadMetadata(long BadgeID) + { + BadgeData result; + result.BadgeId = BadgeID; + result.BadgeName = BadgeID.ToString(); + result.BadgeCreatorName = "Unknown"; + string metaFile = (GlobalVars.UserConfiguration.MapPath.Replace(".rbxl", "").Replace(".rbxlx", "").Replace(".bz2", "") + MetadataFileExtension); + + if (GlobalVars.GameOpened == ScriptType.EasterEgg) + { + metaFile = ((GlobalPaths.DataDir + "\\Appreciation.rbxl").Replace(".rbxl", MetadataFileExtension)); + } + + if (File.Exists(metaFile)) + { + try + { + INIFile metaIni = new INIFile(metaFile); + string section = BadgeID.ToString(); + + string name = metaIni.IniReadValue(section, "BadgeName", BadgeID.ToString()); + string creator = metaIni.IniReadValue(section, "BadgeCreatorName", "Unknown"); + result.BadgeName = name; + result.BadgeCreatorName = creator; + } + catch (Exception) + { + } + } + + return result; + } + + public override bool IsValidURL(string absolutePath, string host) + { + return absolutePath.EndsWith("/game/badge/awardbadge.ashx"); + } + + string GenerateBadgeString(string creatorName, string badgeName, long id) + { + if (PlayerHasBadge(id)) + { + return "0"; + } + + return GlobalVars.UserConfiguration.PlayerName + " won " + creatorName + "'s \"" + badgeName + "\" award!"; + } + + public override async Task OnRequest(object sender, SessionEventArgs e) + { + await Util.Delay(1000); + string query = e.HttpClient.Request.RequestUri.Query; + long badgeid = 0; + long userid = 0; + if (!long.TryParse(NetFuncs.FindQueryString(query, "badgeid"), out badgeid) && + !long.TryParse(NetFuncs.FindQueryString(query, "userid"), out userid)) + { + e.GenericResponse("", HttpStatusCode.BadRequest); + return; + } + + BadgeData meta = LoadMetadata(badgeid); + + string badgeAwardString = GenerateBadgeString(meta.BadgeCreatorName, meta.BadgeName, badgeid); + AddBadgeToDB(badgeid, true); + e.Ok(badgeAwardString, NetFuncs.GenerateHeaders(badgeAwardString.Length.ToString())); + } +} \ No newline at end of file diff --git a/defaultaddons/novetusexts/webproxy/StudioLaunchPage.cs b/defaultaddons/novetusexts/webproxy/StudioLaunchPage.cs index dcb744c..9eaf555 100644 --- a/defaultaddons/novetusexts/webproxy/StudioLaunchPage.cs +++ b/defaultaddons/novetusexts/webproxy/StudioLaunchPage.cs @@ -16,6 +16,11 @@ public class StudioLaunchPage : IWebProxyExtension return "Studio Launch Page Extension"; } + public override string Author() + { + return "Bitl"; + } + public override bool IsValidURL(string absolutePath, string host) { return absolutePath.EndsWith("/ide/landing.aspx") || absolutePath.EndsWith("/my/places.aspx"); diff --git a/defaultaddons/novetusexts/webproxy/UploadWarnings.cs b/defaultaddons/novetusexts/webproxy/UploadWarnings.cs index cac5430..7048ae7 100644 --- a/defaultaddons/novetusexts/webproxy/UploadWarnings.cs +++ b/defaultaddons/novetusexts/webproxy/UploadWarnings.cs @@ -16,6 +16,11 @@ public class UploadWarnings : IWebProxyExtension return "Upload Dialog Warnings Extension"; } + public override string Author() + { + return "Bitl"; + } + public override bool IsValidURL(string absolutePath, string host) { return absolutePath.EndsWith("/uploadmedia/postimage.aspx") || absolutePath.EndsWith("/uploadmedia/uploadvideo.aspx"); diff --git a/scripts/batch/clean_junk.bat b/scripts/batch/clean_junk.bat index 1330c2d..a194752 100644 --- a/scripts/batch/clean_junk.bat +++ b/scripts/batch/clean_junk.bat @@ -108,6 +108,7 @@ del /s /q Novetus\config\ReShade.ini del /s /q Novetus\config\config.ini del /s /q Novetus\config\config_customization.ini del /s /q Novetus\config\initialfilelist.txt +del /s /q Novetus\config\BadgeDatabase.ini del /s /q Novetus\config\clients\GlobalSettings2_2007E.xml del /s /q Novetus\config\clients\GlobalSettings2_2007E-Shaders.xml diff --git a/scripts/launcher/Appreciation.rbxl b/scripts/launcher/Appreciation.rbxl index eb6f3db..44b4cd2 100644 --- a/scripts/launcher/Appreciation.rbxl +++ b/scripts/launcher/Appreciation.rbxl @@ -1,23 +1,10 @@ null nil - + - Run Service - true - - - - - Selection - true - - - - - 0 - true - RBX0 + RBX1 + 56.700002957135439 0 0 @@ -33,49 +20,11 @@ 1 Workspace - RBX1 + RBX2 true - + - null - 0 - - 9.39895344 - 21.2737999 - 50.021347 - 0.999782801 - 0.011853327 - -0.0171419401 - -1.86264515e-009 - 0.822510302 - 0.568750203 - 0.0208410043 - -0.568626702 - 0.822331667 - - - 9.74179173 - 9.89881229 - 33.5747375 - 1 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - - Camera - true - - - - - 0 - true 0 0 @@ -91,10 +40,10 @@ 1 Base - RBX2 + RBX4 true - + true -0.5 @@ -121,10 +70,6 @@ 1 true - false - 0 - true - true false 0.5 1 @@ -138,6 +83,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -167,8 +113,40 @@ 64 + + + BadgeID + 2018 + true + + + + + false + + Script + print("Badge Awarder Loaded. BadgeID:" .. script.Parent.BadgeID.Value) + +-- ROBLOX scripter hackers, see what you can do with this: +-- game:GetService("BadgeService"):UserHasBadge(userid, badgeid) + +function OnTouch(part) + if (part.Parent:FindFirstChild("Humanoid") ~= nil) then + local p = game.Players:GetPlayerFromCharacter(part.Parent) + if (p ~= nil) then + print("Awarding BadgeID: " ..script.Parent.BadgeID.Value .. " to UserID: " .. p.userId) + local b = game:GetService("BadgeService") + b:AwardBadge(p.userId, script.Parent.BadgeID.Value) + end + end +end + +script.Parent.Touched:connect(OnTouch) + true + + - + true -0.5 @@ -195,10 +173,6 @@ 0 true - false - 0 - true - true false 0.5 1 @@ -212,6 +186,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -242,7 +217,7 @@ - + true -0.5 @@ -269,10 +244,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -286,6 +257,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -316,7 +288,7 @@ - + true -0.5 @@ -343,10 +315,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -360,6 +328,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -390,7 +359,7 @@ - + true -0.5 @@ -417,10 +386,6 @@ 0 false - true - 0 - true - true false 0.5 1 @@ -434,6 +399,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -465,10 +431,8 @@ - + - 0 - true 0 0 @@ -484,10 +448,10 @@ 1 Bitl - RBX3 + RBX12 true - + true -0.5 @@ -514,13 +478,9 @@ -1 true - true - 0 - true - true false 0.5 - 0 + 1 0.300000012 -0.5 0.5 @@ -531,6 +491,7 @@ 0 0 true + 256 Head 0 -0.5 @@ -560,21 +521,33 @@ 1 - + + 2 + 2 0 Mesh + + 0 + 0 + 0 + 1.25 1.25 1.25 + + 1 + 1 + 1 + true - + 5 face @@ -585,7 +558,7 @@ - + true -0.5 @@ -612,13 +585,9 @@ -1 true - true - 0 - true - true false 0.5 - 0 + 1 0.300000012 -0.5 0.5 @@ -629,6 +598,7 @@ 2 0 true + 256 Torso 0 0 @@ -658,7 +628,7 @@ 1 - + 5 Decal @@ -669,7 +639,7 @@ - + true -0.5 @@ -696,13 +666,9 @@ -1 true - true - 0 - true - true false 0.5 - 0 + 1 0.300000012 -0.5 0.5 @@ -713,6 +679,7 @@ 0 0 true + 256 Left Arm 0 -0.5 @@ -743,7 +710,7 @@ - + true -0.5 @@ -770,13 +737,9 @@ -1 true - true - 0 - true - true false 0.5 - 0 + 1 0.300000012 -0.5 0.5 @@ -787,6 +750,7 @@ 0 0 true + 256 Right Arm 0 -0.5 @@ -817,7 +781,7 @@ - + true -0.5 @@ -844,13 +808,9 @@ -1 true - true - 0 - true - true false 0.5 - 0 + 1 0.300000012 -0.5 0.5 @@ -861,6 +821,7 @@ 0 0 true + 256 Left Leg 0 -0.5 @@ -891,7 +852,7 @@ - + true -0.5 @@ -918,13 +879,9 @@ -1 true - true - 0 - true - true false 0.5 - 0 + 1 0.300000012 -0.5 0.5 @@ -935,6 +892,7 @@ 0 0 true + 256 Right Leg 0 -0.5 @@ -965,7 +923,7 @@ - + true -0.5 @@ -992,13 +950,9 @@ 1 true - true - 0 - true - true false 0.5 - 2 + 1 0.300000012 -0.5 0.5 @@ -1009,6 +963,7 @@ 0 0 true + 256 Hat 0 -0.5 @@ -1038,22 +993,34 @@ 1 - + + 2 + 2 rbxasset://../../../shareddata/charcustom/hats/fonts/tophat.mesh 5 Mesh + + 0 + 0 + 0 + 1 1 1 rbxasset://../../../shareddata/charcustom/hats/textures/RedTopHat.png + + 1 + 1 + 1 + true - + true -0.5 @@ -1080,13 +1047,9 @@ 1 true - true - 0 - true - true false 0.5 - 0 + 1 0.300000012 -0.5 0.5 @@ -1097,6 +1060,7 @@ 0 0 true + 256 Swordpack 0 -0.5 @@ -1126,26 +1090,36 @@ 1 - + + 2 + 2 rbxasset://../../../shareddata/charcustom/hats/fonts/Swordpack.mesh 5 Mesh + + 0 + 0 + 0 + 1 1 1 rbxasset://../../../shareddata/charcustom/hats/textures/Swordpack.png + + 1 + 1 + 1 + true - + - 0 - true 0 0 @@ -1161,10 +1135,10 @@ 1 Icon - RBX4 + RBX26 true - + true -0.5 @@ -1191,10 +1165,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -1208,6 +1178,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -1238,7 +1209,7 @@ - + true -0.5 @@ -1265,10 +1236,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -1282,6 +1249,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -1312,7 +1280,7 @@ - + true -0.5 @@ -1339,10 +1307,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -1356,6 +1320,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -1386,7 +1351,7 @@ - + true -0.5 @@ -1413,10 +1378,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -1430,6 +1391,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -1460,7 +1422,7 @@ - + true -0.5 @@ -1487,10 +1449,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -1504,6 +1462,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -1535,10 +1494,8 @@ - + - 0 - true 0 0 @@ -1554,10 +1511,10 @@ 1 Room - RBX1 + RBX2 true - + true -0.5 @@ -1584,10 +1541,6 @@ 0 true - false - 0 - true - true false 0.5 1 @@ -1601,6 +1554,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -1631,7 +1585,7 @@ - + true -0.5 @@ -1658,10 +1612,6 @@ 0 false - false - 0 - true - true false 0.5 1 @@ -1675,6 +1625,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -1704,16 +1655,29 @@ 64 - + false + DoorEnter - brick = script.Parent messageText = "Epilepsy Warning: Flashing lights. Don't press the button if you've had a history of seizures." message = Instance.new("Hint") message.Name = "Warning" message.Text = messageText function onHit(hit) if (hit.Parent:findFirstChild("Humanoid") ~= nil) then message.Parent = game.Workspace end end brick.Touched:connect(onHit) + brick = script.Parent +messageText = "Epilepsy Warning: Flashing lights. Don't press the button if you've had a history of seizures." +message = Instance.new("Hint") +message.Name = "Warning" +message.Text = messageText + +function onHit(hit) + if (hit.Parent:findFirstChild("Humanoid") ~= nil) then + message.Parent = game.Workspace + end +end + +brick.Touched:connect(onHit) true - + true -0.5 @@ -1740,10 +1704,6 @@ 0 true - false - 0 - true - true false 0.5 1 @@ -1757,6 +1717,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -1787,7 +1748,7 @@ - + true -0.5 @@ -1814,10 +1775,6 @@ 0 true - false - 0 - true - true false 0.5 1 @@ -1831,6 +1788,7 @@ 0 0 true + 256 Panel 0 -0.5 @@ -1860,7 +1818,7 @@ 64 - + 4 Animation @@ -1871,7 +1829,7 @@ - + true -0.5 @@ -1898,10 +1856,6 @@ 1 true - false - 0 - true - true false 0.5 1 @@ -1915,6 +1869,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -1945,7 +1900,7 @@ - + true -0.5 @@ -1972,10 +1927,6 @@ 1 true - false - 0 - true - true false 0.5 1 @@ -1989,6 +1940,7 @@ 0 0 true + 256 DanceFloor 0 -0.5 @@ -2019,7 +1971,7 @@ - + false -0.5 @@ -2046,10 +1998,6 @@ -1 true - true - 0 - true - true false 0.5 1 @@ -2063,6 +2011,7 @@ 0 0 false + 256 Start 0 -0.5 @@ -2092,18 +2041,61 @@ 5 - + false + ButtonPress - brick = script.Parent animation = script.Parent.Parent.Panel.Animation dancefloor = script.Parent.Parent.DanceFloor messageText = "Art by Voreburger" message = Instance.new("Hint") message.Text = messageText function antonymph() brick.Antonymph:play() message.Parent = game.Workspace while true do animation.Texture = "rbxasset://../../../shareddata/textures/f1_antonymph.png" dancefloor.BrickColor = BrickColor.random() wait(0.2) animation.Texture = "rbxasset://../../../shareddata/textures/f2_of.png" dancefloor.BrickColor = BrickColor.random() wait(0.2) animation.Texture = "rbxasset://../../../shareddata/textures/f3_the.png" dancefloor.BrickColor = BrickColor.random() wait(0.2) animation.Texture = "rbxasset://../../../shareddata/textures/f4_internet.png" dancefloor.BrickColor = BrickColor.random() wait(0.2) end end function onHit(hit) if hit.Parent:findFirstChild("Humanoid") ~= nil then if game.Workspace:findFirstChild("Warning") ~= nil then game.Workspace.Warning:remove() end antonymph() end end brick.Touched:connect(onHit) + brick = script.Parent +animation = script.Parent.Parent.Panel.Animation +dancefloor = script.Parent.Parent.DanceFloor +messageText = "Art by Voreburger" +message = Instance.new("Hint") +message.Text = messageText + +function antonymph() + brick.Antonymph:play() + message.Parent = game.Workspace + + while true do + animation.Texture = "rbxasset://../../../shareddata/textures/f1_antonymph.png" + dancefloor.BrickColor = BrickColor.random() + wait(0.2) + animation.Texture = "rbxasset://../../../shareddata/textures/f2_of.png" + dancefloor.BrickColor = BrickColor.random() + wait(0.2) + animation.Texture = "rbxasset://../../../shareddata/textures/f3_the.png" + dancefloor.BrickColor = BrickColor.random() + wait(0.2) + animation.Texture = "rbxasset://../../../shareddata/textures/f4_internet.png" + dancefloor.BrickColor = BrickColor.random() + wait(0.2) + end +end + +function onHit(hit) + if hit.Parent:findFirstChild("Humanoid") ~= nil then + if game.Workspace:findFirstChild("Warning") ~= nil then + game.Workspace.Warning:remove() + end + local p = game.Players:GetPlayerFromCharacter(hit.Parent) + if p ~= nil then + local b = game:GetService("BadgeService") + b:AwardBadge(p.userId, script.Parent.BadgeID.Value) + end + antonymph() + end +end + +brick.Touched:connect(onHit) true - + true Antonymph + 1 -1 false rbxasset://../../../shareddata/sounds/antonymph.mp3 @@ -2111,7 +2103,7 @@ true - + 1 Warning @@ -2121,12 +2113,17 @@ true + + + BadgeID + 42021 + true + + - + - 0 - true 0 0 @@ -2142,13 +2139,11 @@ 1 THANK YOU! - RBX5 + RBX45 true - + - 0 - true 0 0 @@ -2164,10 +2159,10 @@ 1 THANK - RBX5 + RBX45 true - + true -0.5 @@ -2194,10 +2189,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -2211,6 +2202,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -2241,7 +2233,7 @@ - + true -0.5 @@ -2268,10 +2260,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -2285,6 +2273,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -2315,7 +2304,7 @@ - + true -0.5 @@ -2342,10 +2331,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -2359,6 +2344,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -2389,7 +2375,7 @@ - + true -0.5 @@ -2416,10 +2402,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -2433,6 +2415,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -2463,7 +2446,7 @@ - + true -0.5 @@ -2490,10 +2473,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -2507,6 +2486,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -2537,7 +2517,7 @@ - + true -0.5 @@ -2564,10 +2544,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -2581,6 +2557,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -2611,7 +2588,7 @@ - + true -0.5 @@ -2638,10 +2615,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -2655,6 +2628,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -2685,7 +2659,7 @@ - + true -0.5 @@ -2712,10 +2686,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -2729,6 +2699,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -2759,7 +2730,7 @@ - + true -0.5 @@ -2786,10 +2757,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -2803,6 +2770,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -2833,7 +2801,7 @@ - + true -0.5 @@ -2860,10 +2828,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -2877,6 +2841,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -2907,7 +2872,7 @@ - + true -0.5 @@ -2934,10 +2899,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -2951,6 +2912,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -2981,7 +2943,7 @@ - + true -0.5 @@ -3008,10 +2970,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -3025,6 +2983,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -3055,7 +3014,7 @@ - + true -0.5 @@ -3082,10 +3041,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -3099,6 +3054,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -3129,7 +3085,7 @@ - + true -0.5 @@ -3156,10 +3112,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -3173,6 +3125,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -3203,7 +3156,7 @@ - + true -0.5 @@ -3230,10 +3183,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -3247,6 +3196,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -3277,7 +3227,7 @@ - + true -0.5 @@ -3304,10 +3254,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -3321,6 +3267,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -3351,7 +3298,7 @@ - + true -0.5 @@ -3378,10 +3325,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -3395,6 +3338,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -3425,7 +3369,7 @@ - + true -0.5 @@ -3452,10 +3396,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -3469,6 +3409,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -3499,7 +3440,7 @@ - + true -0.5 @@ -3526,10 +3467,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -3543,6 +3480,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -3573,7 +3511,7 @@ - + true -0.5 @@ -3600,10 +3538,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -3617,6 +3551,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -3648,10 +3583,8 @@ - + - 0 - true 0 0 @@ -3667,10 +3600,10 @@ 1 YOU! - RBX6 + RBX67 true - + true -0.5 @@ -3697,10 +3630,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -3714,6 +3643,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -3744,7 +3674,7 @@ - + true -0.5 @@ -3771,10 +3701,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -3788,6 +3714,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -3818,7 +3745,7 @@ - + true -0.5 @@ -3845,10 +3772,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -3862,6 +3785,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -3892,7 +3816,7 @@ - + true -0.5 @@ -3919,10 +3843,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -3936,6 +3856,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -3966,7 +3887,7 @@ - + true -0.5 @@ -3993,10 +3914,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -4010,6 +3927,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -4040,7 +3958,7 @@ - + true -0.5 @@ -4067,10 +3985,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -4084,6 +3998,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -4114,7 +4029,7 @@ - + true -0.5 @@ -4141,10 +4056,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -4158,6 +4069,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -4188,7 +4100,7 @@ - + true -0.5 @@ -4215,10 +4127,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -4232,6 +4140,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -4262,7 +4171,7 @@ - + true -0.5 @@ -4289,10 +4198,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -4306,6 +4211,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -4336,7 +4242,7 @@ - + true -0.5 @@ -4363,10 +4269,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -4380,6 +4282,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -4410,7 +4313,7 @@ - + true -0.5 @@ -4437,10 +4340,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -4454,6 +4353,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -4484,7 +4384,7 @@ - + true -0.5 @@ -4511,10 +4411,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -4528,6 +4424,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -4558,7 +4455,7 @@ - + true -0.5 @@ -4585,10 +4482,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -4602,6 +4495,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -4632,7 +4526,7 @@ - + true -0.5 @@ -4659,10 +4553,6 @@ 0 true - true - 0 - true - true false 0.5 1 @@ -4676,6 +4566,7 @@ 0 0 true + 256 Part 0 -0.5 @@ -4708,8 +4599,9 @@ - + + false true -0.5 0.5 @@ -4735,11 +4627,8 @@ 1 true - true - 0 - true - true false + 10 0.5 1 0.300000012 @@ -4752,6 +4641,7 @@ 2 0 true + 256 SpawnLocation true 0 @@ -4764,6 +4654,7 @@ 0 0 + 194 -0.5 0.5 0 @@ -4782,7 +4673,7 @@ 6 - + 1 Decal @@ -4793,64 +4684,28 @@ - + null 0 - 0 - 1.10537087e-006 - 1.10537087e-006 - 1 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 + 18.7733498 + 50.8485947 + 70.46241 + 0.987410367 + -0.0628171042 + 0.145171881 + -3.7252903e-009 + 0.917764783 + 0.397124588 + -0.158179849 + -0.392124921 + 0.906210363 - 0 - 0 - -5 - 1 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - - Camera - true - - - - - null - 0 - - 1.87747955 - 36.7402802 - 32.7510681 - 0.99968034 - 0.018067915 - -0.0176865812 - -2.79396772e-009 - 0.699525595 - 0.714607596 - 0.025283685 - -0.714379191 - 0.699301958 - - - 2.23121119 - 22.4481277 - 18.7650299 + 3 + 7.69984436 + -28 1 0 0 @@ -4866,62 +4721,171 @@ - RBX7 - RBX8 - + - Players - true - 10 - - - - - StarterPack + Run Service true - - - Soundscape - true - 10 - 1 - 1 - - RBX9 - RBX10 - RBX11 - RBX12 - RBX13 - RBX14 - RBX15 - RBX16 - RBX17 - RBX18 - RBX19 - RBX20 - RBX21 - RBX22 - - + RBX84 + RBX85 + Instance true - RBX23 - + - 4286221432 - 4278190080 - Lighting - 4291151301 - 14:00:00 - 4292335327 + ContentFilter + true + + + + + Instance + true + + + + + GuiService + true + + + + + 12 + Players + true + + + + + StarterPack + true + + + + + StarterGui + true + true + + + + + 0 + 10 + 1 + Soundscape + 1 + true + + RBX94 + RBX95 + RBX96 + RBX97 + RBX98 + RBX99 + RBX100 + RBX101 + RBX102 + RBX103 + RBX104 + RBX105 + RBX106 + RBX107 + + + + PhysicsService + true + + + + + BadgeService + true + + + + + Geometry + true + + + RBX111 + + + 1000 + Debris + true + + + + + Instance + true + + + + + Instance + true + + + RBX115 + + + Selection + true + + + RBX117 + RBX118 + + + CollectionService + true + + + + + 4286611584 + 1 + 4278190080 + 4278190080 + 41.7332993 + Lighting + 4289967032 + 14:00:00 + true + + + + SkipSecurity + 0 + true + + + + + + ChangeHistoryService + true + + + + + Instance + true + + + + + Teams true - RBX24 - RBX25 \ No newline at end of file -- 2.40.1 From 23e597dede56acedb7668b881edeb0ef9af078db Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 13 Jan 2023 00:16:31 -0700 Subject: [PATCH 28/85] update scripts --- changelog.txt | 7 ++ .../novetusexts/webproxy/AwardBadge.cs | 50 ++++++------ .../novetusexts/webproxy/HasBadge.cs | 76 +++++++++++++++++++ .../novetusexts/webproxy/StaticPages.cs | 71 +++++++++++++++++ .../novetusexts/webproxy/StudioLaunchPage.cs | 33 -------- .../novetusexts/webproxy/UploadWarnings.cs | 12 ++- 6 files changed, 190 insertions(+), 59 deletions(-) create mode 100644 defaultaddons/novetusexts/webproxy/HasBadge.cs create mode 100644 defaultaddons/novetusexts/webproxy/StaticPages.cs delete mode 100644 defaultaddons/novetusexts/webproxy/StudioLaunchPage.cs diff --git a/changelog.txt b/changelog.txt index 04cc096..41a98c4 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ 1.3 Snapshot v22.8412.32591.1 Enhancements: +- Added support for HasBadge to the Web Proxy. +- Merged some static APIs into one extension. +- Restored the Help button functionality. +- All clients now work properly with the Web Proxy. +---------------------------------------------------------------------------- +1.3 Snapshot v22.8412.32591.1 +Enhancements: - Added badge support to the Web Proxy. - The Easter Egg now loads up a server and a client, rather than loading a client in Play Solo mode. - Further improved web proxy reliability. diff --git a/defaultaddons/novetusexts/webproxy/AwardBadge.cs b/defaultaddons/novetusexts/webproxy/AwardBadge.cs index d8e498e..8dd4e07 100644 --- a/defaultaddons/novetusexts/webproxy/AwardBadge.cs +++ b/defaultaddons/novetusexts/webproxy/AwardBadge.cs @@ -20,20 +20,10 @@ public class AwardBadge : IWebProxyExtension } private static readonly string BadgeDatabasePath = GlobalPaths.ConfigDir + "\\BadgeDatabase.ini"; - private string BadgeDatabaseSection = "BadgeDatabase"; + private static readonly string BadgeDatabaseSection = "BadgeDatabase"; private string MetadataFileExtension = "_meta.ini"; private INIFile ini = new INIFile(BadgeDatabasePath); - public override string Name() - { - return "Badge Award Extension"; - } - - public override string Author() - { - return "Bitl"; - } - void AddBadgeToDB(long BadgeID, bool Awarded = false) { CreateBadgeDatabaseIfNeeded(); @@ -62,11 +52,6 @@ public class AwardBadge : IWebProxyExtension } } - public override void OnExtensionLoad() - { - CreateBadgeDatabaseIfNeeded(); - } - BadgeData LoadMetadata(long BadgeID) { BadgeData result; @@ -100,11 +85,6 @@ public class AwardBadge : IWebProxyExtension return result; } - public override bool IsValidURL(string absolutePath, string host) - { - return absolutePath.EndsWith("/game/badge/awardbadge.ashx"); - } - string GenerateBadgeString(string creatorName, string badgeName, long id) { if (PlayerHasBadge(id)) @@ -115,9 +95,33 @@ public class AwardBadge : IWebProxyExtension return GlobalVars.UserConfiguration.PlayerName + " won " + creatorName + "'s \"" + badgeName + "\" award!"; } + public override string Name() + { + return "Badge Award API Extension"; + } + + public override string Version() + { + return "1.0.1"; + } + + public override string Author() + { + return "Bitl"; + } + + public override void OnExtensionLoad() + { + CreateBadgeDatabaseIfNeeded(); + } + + public override bool IsValidURL(string absolutePath, string host) + { + return absolutePath.EndsWith("/game/badge/awardbadge.ashx"); + } + public override async Task OnRequest(object sender, SessionEventArgs e) { - await Util.Delay(1000); string query = e.HttpClient.Request.RequestUri.Query; long badgeid = 0; long userid = 0; @@ -132,6 +136,6 @@ public class AwardBadge : IWebProxyExtension string badgeAwardString = GenerateBadgeString(meta.BadgeCreatorName, meta.BadgeName, badgeid); AddBadgeToDB(badgeid, true); - e.Ok(badgeAwardString, NetFuncs.GenerateHeaders(badgeAwardString.Length.ToString())); + e.Ok(badgeAwardString, NetFuncs.GenerateHeaders(badgeAwardString.Length.ToString(), "text/plain")); } } \ No newline at end of file diff --git a/defaultaddons/novetusexts/webproxy/HasBadge.cs b/defaultaddons/novetusexts/webproxy/HasBadge.cs new file mode 100644 index 0000000..d674893 --- /dev/null +++ b/defaultaddons/novetusexts/webproxy/HasBadge.cs @@ -0,0 +1,76 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using System.Web; +using System.Net; +using System.Collections.Generic; +using Titanium.Web.Proxy; +using Titanium.Web.Proxy.EventArguments; +using Titanium.Web.Proxy.Http; +using Titanium.Web.Proxy.Models; +using Novetus.Core; + +public class HasBadge : IWebProxyExtension +{ + private static readonly string BadgeDatabasePath = GlobalPaths.ConfigDir + "\\BadgeDatabase.ini"; + private static readonly string BadgeDatabaseSection = "BadgeDatabase"; + private INIFile ini = new INIFile(BadgeDatabasePath); + + public override string Name() + { + return "Badge Checker API Extension"; + } + + public override string Author() + { + return "Bitl"; + } + + bool PlayerHasBadge(long BadgeID) + { + CreateBadgeDatabaseIfNeeded(); + + if (ini.IniValueExists(BadgeID.ToString())) + { + string awarded = ini.IniReadValue(BadgeDatabaseSection, BadgeID.ToString(), "False"); + return Convert.ToBoolean(awarded); + } + + return false; + } + + void CreateBadgeDatabaseIfNeeded() + { + if (!File.Exists(BadgeDatabasePath)) + { + Util.ConsolePrint("WARNING - " + BadgeDatabasePath + " not found. Creating empty badge database.", 5); + File.Create(BadgeDatabasePath).Dispose(); + } + } + + public override void OnExtensionLoad() + { + CreateBadgeDatabaseIfNeeded(); + } + + public override bool IsValidURL(string absolutePath, string host) + { + return absolutePath.EndsWith("/game/badge/hasbadge.ashx"); + } + + public override async Task OnRequest(object sender, SessionEventArgs e) + { + string query = e.HttpClient.Request.RequestUri.Query; + long badgeid = 0; + long userid = 0; + if (!long.TryParse(NetFuncs.FindQueryString(query, "badgeid"), out badgeid) && + !long.TryParse(NetFuncs.FindQueryString(query, "userid"), out userid)) + { + e.GenericResponse("", HttpStatusCode.BadRequest); + return; + } + + string hasBadgeResult = PlayerHasBadge(badgeid) ? "Success" : "Failure"; + e.Ok(hasBadgeResult, NetFuncs.GenerateHeaders(hasBadgeResult.Length.ToString(), "text/plain")); + } +} \ No newline at end of file diff --git a/defaultaddons/novetusexts/webproxy/StaticPages.cs b/defaultaddons/novetusexts/webproxy/StaticPages.cs new file mode 100644 index 0000000..f809edc --- /dev/null +++ b/defaultaddons/novetusexts/webproxy/StaticPages.cs @@ -0,0 +1,71 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using System.Web; +using System.Collections.Generic; +using System.Linq; +using Titanium.Web.Proxy; +using Titanium.Web.Proxy.EventArguments; +using Titanium.Web.Proxy.Http; +using Titanium.Web.Proxy.Models; +using Novetus.Core; + +public class StaticPages : IWebProxyExtension +{ + public override string Name() + { + return "Static APIs Extension"; + } + + public override string Author() + { + return "Bitl"; + } + + static string GetStudioPageOutput() + { + return "Welcome to Novetus " + GlobalVars.ProgramInformation.Version + "!"; + } + + static string GetHelpPageOutput() + { + string path = GlobalPaths.NovetusExtsWebProxy + @"\\webpages\\Help.html"; + return File.ReadAllText(path); + } + + Dictionary staticPages = new Dictionary() + { + {"/ide/landing.aspx", GetStudioPageOutput()}, + {"/discover", GetStudioPageOutput()}, + {"/my/places.aspx", GetStudioPageOutput()}, + {"/game/badge/isbadgedisabled.ashx", "0"}, + {"/game/help.aspx", GetHelpPageOutput()} + }; + + public override bool IsValidURL(string absolutePath, string host) + { + foreach(var item in staticPages.Keys) + { + if (absolutePath.StartsWith(item) || absolutePath.EndsWith(item)) + { + return true; + } + } + + return false; + } + + public override async Task OnRequest(object sender, SessionEventArgs e) + { + string absPath = e.HttpClient.Request.RequestUri.AbsolutePath.ToLowerInvariant(); + + foreach(var item in staticPages.Keys) + { + if (absPath.StartsWith(item) || absPath.EndsWith(item)) + { + string result = staticPages[item]; + e.Ok(result, NetFuncs.GenerateHeaders(result.Length.ToString(), "text/html")); + } + } + } +} \ No newline at end of file diff --git a/defaultaddons/novetusexts/webproxy/StudioLaunchPage.cs b/defaultaddons/novetusexts/webproxy/StudioLaunchPage.cs deleted file mode 100644 index 9eaf555..0000000 --- a/defaultaddons/novetusexts/webproxy/StudioLaunchPage.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.IO; -using System.Threading.Tasks; -using System.Web; -using System.Collections.Generic; -using Titanium.Web.Proxy; -using Titanium.Web.Proxy.EventArguments; -using Titanium.Web.Proxy.Http; -using Titanium.Web.Proxy.Models; -using Novetus.Core; - -public class StudioLaunchPage : IWebProxyExtension -{ - public override string Name() - { - return "Studio Launch Page Extension"; - } - - public override string Author() - { - return "Bitl"; - } - - public override bool IsValidURL(string absolutePath, string host) - { - return absolutePath.EndsWith("/ide/landing.aspx") || absolutePath.EndsWith("/my/places.aspx"); - } - - public override async Task OnRequest(object sender, SessionEventArgs e) - { - e.Ok("Welcome to Novetus Studio version " + GlobalVars.ProgramInformation.Version); - } -} \ No newline at end of file diff --git a/defaultaddons/novetusexts/webproxy/UploadWarnings.cs b/defaultaddons/novetusexts/webproxy/UploadWarnings.cs index 7048ae7..18d9dee 100644 --- a/defaultaddons/novetusexts/webproxy/UploadWarnings.cs +++ b/defaultaddons/novetusexts/webproxy/UploadWarnings.cs @@ -16,6 +16,11 @@ public class UploadWarnings : IWebProxyExtension return "Upload Dialog Warnings Extension"; } + public override string Version() + { + return "1.0.1"; + } + public override string Author() { return "Bitl"; @@ -31,14 +36,15 @@ public class UploadWarnings : IWebProxyExtension string absPath = e.HttpClient.Request.RequestUri.AbsolutePath.ToLowerInvariant(); string type = "video"; - string folder = "Videos"; + string folder = "My Videos"; if (absPath.EndsWith("/uploadmedia/postimage.aspx")) { type = "screenshot"; - folder = "Pictures"; + folder = "My Pictures"; } - e.Ok("Your " + type + " was saved! Look in the Roblox folder in your " + folder + " folder!"); + string result = "Your " + type + " was saved! Look in the Roblox folder in your " + folder + " folder!"; + e.Ok(result, NetFuncs.GenerateHeaders(result.Length.ToString(), "text/plain")); } } \ No newline at end of file -- 2.40.1 From 2305148e7bcd34aaa995691f9e77a106e0b15f63 Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 13 Jan 2023 13:41:00 -0700 Subject: [PATCH 29/85] Code refactor --- .../Novetus.Bootstrapper.csproj | 133 +- Novetus/Novetus.Bootstrapper/packages.config | 46 + .../Classes/LocalVars.cs | 24 - .../ClientScriptTester.cs | 29 - .../Forms/ClientScriptTestForm.Designer.cs | 95 - .../Forms/ClientScriptTestForm.cs | 35 - .../Forms/ClientScriptTestForm.resx | 1819 ----------------- .../Novetus.ClientScriptTester.csproj | 113 - .../NovetusIcon.ico | Bin 135503 -> 0 bytes .../Properties/AssemblyInfo.cs | 33 - .../Properties/Resources.Designer.cs | 63 - .../Properties/Resources.resx | 117 -- .../Properties/Settings.Designer.cs | 26 - .../Properties/Settings.settings | 7 - .../Resources/ClientScriptTester.ico | Bin 101595 -> 0 bytes .../Resources/NovetusIcon.ico | Bin 135503 -> 0 bytes Novetus/Novetus.ClientScriptTester/app.config | 19 - .../Novetus.ClientScriptTester/app.manifest | 76 - .../Novetus.Internal.ReleasePreparer.csproj | 76 - .../Novetus.ReleasePreparer/NovetusIcon.ico | Bin 135503 -> 0 bytes .../Properties/AssemblyInfo.cs | 34 - .../ReleasePreparer.cs | 156 -- .../Resources/NovetusIcon.ico | Bin 135503 -> 0 bytes Novetus/Novetus.ReleasePreparer/app.config | 3 - Novetus/Novetus.Tools.sln | 31 - Novetus/NovetusCore/Classes/IDiscordRPC.cs | 57 +- Novetus/NovetusCore/NovetusCore.projitems | 3 + .../StorageAndFunctions/ClientManagement.cs | 172 +- .../StorageAndFunctions/FileManagement.cs | 117 +- .../StorageAndFunctions/GlobalVars.cs | 6 +- .../StorageAndFunctions/NetFuncs.cs | 83 +- .../StorageAndFunctions/NovetusFuncs.cs | 609 +----- .../Roblox Helpers/RobloxTypes.cs | 163 ++ .../Roblox Helpers/RobloxXML.cs | 203 ++ .../Roblox Helpers/Vector3.cs | 18 + .../StorageAndFunctions/SecurityFuncs.cs | 240 +-- .../NovetusCore/StorageAndFunctions/Util.cs | 158 -- .../Classes/Launcher/SplashLoader.cs | 2 +- .../Classes/TabControlWithoutHeader.cs | 22 + .../Forms/LauncherForm/LauncherFormShared.cs | 2 +- .../NovetusLauncher/Forms/NovetusConsole.cs | 27 +- .../Forms/SDK/ClientinfoCreator.cs | 70 +- .../NovetusLauncher/Forms/ServerBrowser.cs | 14 +- .../NovetusLauncher/Novetus.Launcher.csproj | 141 +- .../NovetusLauncherEntryPoint.cs | 4 +- Novetus/NovetusLauncher/packages.config | 46 + Novetus/NovetusURI/Classes/LocalFuncs.cs | 8 +- Novetus/NovetusURI/Forms/LoaderForm.cs | 49 +- Novetus/NovetusURI/Novetus.URI.csproj | 135 +- Novetus/NovetusURI/packages.config | 46 + SECURITY.md | 9 +- changelog.txt | 1 + 52 files changed, 1498 insertions(+), 3842 deletions(-) delete mode 100644 Novetus/Novetus.ClientScriptTester/Classes/LocalVars.cs delete mode 100644 Novetus/Novetus.ClientScriptTester/ClientScriptTester.cs delete mode 100644 Novetus/Novetus.ClientScriptTester/Forms/ClientScriptTestForm.Designer.cs delete mode 100644 Novetus/Novetus.ClientScriptTester/Forms/ClientScriptTestForm.cs delete mode 100644 Novetus/Novetus.ClientScriptTester/Forms/ClientScriptTestForm.resx delete mode 100644 Novetus/Novetus.ClientScriptTester/Novetus.ClientScriptTester.csproj delete mode 100644 Novetus/Novetus.ClientScriptTester/NovetusIcon.ico delete mode 100644 Novetus/Novetus.ClientScriptTester/Properties/AssemblyInfo.cs delete mode 100644 Novetus/Novetus.ClientScriptTester/Properties/Resources.Designer.cs delete mode 100644 Novetus/Novetus.ClientScriptTester/Properties/Resources.resx delete mode 100644 Novetus/Novetus.ClientScriptTester/Properties/Settings.Designer.cs delete mode 100644 Novetus/Novetus.ClientScriptTester/Properties/Settings.settings delete mode 100644 Novetus/Novetus.ClientScriptTester/Resources/ClientScriptTester.ico delete mode 100644 Novetus/Novetus.ClientScriptTester/Resources/NovetusIcon.ico delete mode 100644 Novetus/Novetus.ClientScriptTester/app.config delete mode 100644 Novetus/Novetus.ClientScriptTester/app.manifest delete mode 100644 Novetus/Novetus.ReleasePreparer/Novetus.Internal.ReleasePreparer.csproj delete mode 100644 Novetus/Novetus.ReleasePreparer/NovetusIcon.ico delete mode 100644 Novetus/Novetus.ReleasePreparer/Properties/AssemblyInfo.cs delete mode 100644 Novetus/Novetus.ReleasePreparer/ReleasePreparer.cs delete mode 100644 Novetus/Novetus.ReleasePreparer/Resources/NovetusIcon.ico delete mode 100644 Novetus/Novetus.ReleasePreparer/app.config delete mode 100644 Novetus/Novetus.Tools.sln create mode 100644 Novetus/NovetusCore/StorageAndFunctions/Roblox Helpers/RobloxTypes.cs create mode 100644 Novetus/NovetusCore/StorageAndFunctions/Roblox Helpers/RobloxXML.cs create mode 100644 Novetus/NovetusCore/StorageAndFunctions/Roblox Helpers/Vector3.cs create mode 100644 Novetus/NovetusLauncher/Classes/TabControlWithoutHeader.cs diff --git a/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj b/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj index b41674f..2aa5177 100644 --- a/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj +++ b/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj @@ -12,6 +12,8 @@ 512 false + + AnyCPU @@ -41,17 +43,141 @@ app.manifest + + ..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll + True + True + ..\packages\NLog.5.1.0\lib\net46\NLog.dll + + ..\packages\System.AppContext.4.3.0\lib\net463\System.AppContext.dll + True + True + + + + ..\packages\System.Console.4.3.0\lib\net46\System.Console.dll + True + True + - + + ..\packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll + + + ..\packages\System.Diagnostics.Tracing.4.3.0\lib\net462\System.Diagnostics.Tracing.dll + True + True + + + ..\packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll + True + True + + + ..\packages\System.IO.4.3.0\lib\net462\System.IO.dll + True + True + + + ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll + True + True + + + + ..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll + True + True + + + ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll + True + True + + + ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll + True + True + + + ..\packages\System.Linq.4.3.0\lib\net463\System.Linq.dll + True + True + + + ..\packages\System.Linq.Expressions.4.3.0\lib\net463\System.Linq.Expressions.dll + True + True + + + ..\packages\System.Net.Http.4.3.0\lib\net46\System.Net.Http.dll + True + True + + + ..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll + True + True + + + ..\packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll + True + True + + + ..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll + True + True + + + ..\packages\System.Runtime.Extensions.4.3.0\lib\net462\System.Runtime.Extensions.dll + True + True + + + ..\packages\System.Runtime.InteropServices.4.3.0\lib\net463\System.Runtime.InteropServices.dll + True + True + + + ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + True + + + ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll + True + True + + + ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + True + True + + + ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + True + True + + + ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + True + True + + + ..\packages\System.Text.RegularExpressions.4.3.0\lib\net463\System.Text.RegularExpressions.dll + True + True + @@ -61,6 +187,11 @@ + + ..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll + True + True + diff --git a/Novetus/Novetus.Bootstrapper/packages.config b/Novetus/Novetus.Bootstrapper/packages.config index 5a7cee2..5ff341a 100644 --- a/Novetus/Novetus.Bootstrapper/packages.config +++ b/Novetus/Novetus.Bootstrapper/packages.config @@ -1,4 +1,50 @@  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Novetus/Novetus.ClientScriptTester/Classes/LocalVars.cs b/Novetus/Novetus.ClientScriptTester/Classes/LocalVars.cs deleted file mode 100644 index 5f225d6..0000000 --- a/Novetus/Novetus.ClientScriptTester/Classes/LocalVars.cs +++ /dev/null @@ -1,24 +0,0 @@ -#region Usings -using System; -using System.Collections.Generic; -using System.Diagnostics.Contracts; -#endregion - -namespace Novetus.ClientScriptTester -{ - #region LocalVars - class LocalVars - { - public static List SharedArgs = new List(); - //a re-implementation of "Environment.NewLine" but with double spaces. Should be in NETExt, but we only use it here. - public static String DoubleSpacedNewLine - { - get - { - Contract.Ensures(Contract.Result() != null); - return "\r\n\r\n"; - } - } - } - #endregion -} diff --git a/Novetus/Novetus.ClientScriptTester/ClientScriptTester.cs b/Novetus/Novetus.ClientScriptTester/ClientScriptTester.cs deleted file mode 100644 index 6591f6a..0000000 --- a/Novetus/Novetus.ClientScriptTester/ClientScriptTester.cs +++ /dev/null @@ -1,29 +0,0 @@ -#region Usings -using System; -using System.Windows.Forms; -#endregion - -namespace Novetus.ClientScriptTester -{ - #region ClientScript Tester - static class ClientScriptTester - { - /// - /// The main entry point for the application. - /// - [STAThread] - static void Main(string[] args) - { - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - - foreach (string s in args) - { - LocalVars.SharedArgs.Add(s); - } - - Application.Run(new ClientScriptTestForm()); - } - } - #endregion -} diff --git a/Novetus/Novetus.ClientScriptTester/Forms/ClientScriptTestForm.Designer.cs b/Novetus/Novetus.ClientScriptTester/Forms/ClientScriptTestForm.Designer.cs deleted file mode 100644 index 0b35067..0000000 --- a/Novetus/Novetus.ClientScriptTester/Forms/ClientScriptTestForm.Designer.cs +++ /dev/null @@ -1,95 +0,0 @@ -namespace Novetus.ClientScriptTester -{ - partial class ClientScriptTestForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ClientScriptTestForm)); - this.ResultLabel = new System.Windows.Forms.Label(); - this.Divider1 = new System.Windows.Forms.Label(); - this.OutputBox = new System.Windows.Forms.RichTextBox(); - this.SuspendLayout(); - // - // ResultLabel - // - this.ResultLabel.AutoSize = true; - this.ResultLabel.Location = new System.Drawing.Point(12, 9); - this.ResultLabel.Name = "ResultLabel"; - this.ResultLabel.Size = new System.Drawing.Size(102, 13); - this.ResultLabel.TabIndex = 0; - this.ResultLabel.Text = "Here are the results:"; - // - // Divider1 - // - this.Divider1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.Divider1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; - this.Divider1.Location = new System.Drawing.Point(8, 31); - this.Divider1.Name = "Divider1"; - this.Divider1.Size = new System.Drawing.Size(780, 2); - this.Divider1.TabIndex = 1; - // - // OutputBox - // - this.OutputBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.OutputBox.BackColor = System.Drawing.SystemColors.ControlLightLight; - this.OutputBox.Location = new System.Drawing.Point(8, 36); - this.OutputBox.Name = "OutputBox"; - this.OutputBox.ReadOnly = true; - this.OutputBox.Size = new System.Drawing.Size(780, 402); - this.OutputBox.TabIndex = 2; - this.OutputBox.Text = ""; - // - // ClientScriptTestForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.BackColor = System.Drawing.SystemColors.ControlLightLight; - this.ClientSize = new System.Drawing.Size(800, 450); - this.Controls.Add(this.OutputBox); - this.Controls.Add(this.Divider1); - this.Controls.Add(this.ResultLabel); - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MinimumSize = new System.Drawing.Size(816, 200); - this.Name = "ClientScriptTestForm"; - this.Text = "ClientScript Tester"; - this.Load += new System.EventHandler(this.ClientScriptTestForm_Load); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - - private System.Windows.Forms.Label ResultLabel; - private System.Windows.Forms.Label Divider1; - private System.Windows.Forms.RichTextBox OutputBox; - } -} - diff --git a/Novetus/Novetus.ClientScriptTester/Forms/ClientScriptTestForm.cs b/Novetus/Novetus.ClientScriptTester/Forms/ClientScriptTestForm.cs deleted file mode 100644 index f80626d..0000000 --- a/Novetus/Novetus.ClientScriptTester/Forms/ClientScriptTestForm.cs +++ /dev/null @@ -1,35 +0,0 @@ -#region Usings -using System; -using System.Windows.Forms; -#endregion - -namespace Novetus.ClientScriptTester -{ - #region ClientScriptTestForm - public partial class ClientScriptTestForm : Form - { - #region Constructor - public ClientScriptTestForm() - { - InitializeComponent(); - } - #endregion - - #region Form Events - private void ClientScriptTestForm_Load(object sender, EventArgs e) - { - foreach (string str in LocalVars.SharedArgs) - { - if (!string.IsNullOrWhiteSpace(str)) - { - OutputBox.AppendText(str + LocalVars.DoubleSpacedNewLine); - } - } - - OutputBox.SelectionStart = 0; - OutputBox.ScrollToCaret(); - } - #endregion - } - #endregion -} diff --git a/Novetus/Novetus.ClientScriptTester/Forms/ClientScriptTestForm.resx b/Novetus/Novetus.ClientScriptTester/Forms/ClientScriptTestForm.resx deleted file mode 100644 index a237f57..0000000 --- a/Novetus/Novetus.ClientScriptTester/Forms/ClientScriptTestForm.resx +++ /dev/null @@ -1,1819 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - - 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 - /gbs72bzX//8pfD+0fhw772TaH5ar/+bPcF2+QKAYgIAxQQAigkAFBMAKCYAUEwAoJgAQDEBgGICAMUE - AIoJABQTACgmAFBMAKDY7mYcf5Nc4A9//vuVcP5q+A4f2vL8S1ueP06GD/YWi2j+IBofjg7DfQ5H56P5 - v/3j1j+jCwzDH8P5rfIFAMUEAIoJABQTACgmAFBMAKCYAEAxAYBiAgDFBACKCQAUEwAoJgBQTACgmABA - sf8BK8YyIA0V98sAAAAASUVORK5CYIIoAAAAgAAAAAABAAABACAAAAAAAAAAAQDDDgAAww4AAAAAAAAA - AAAAj1owFI9aMBSPWjAUj1owFI9aMBSPWjAUj1owFI9aMBSPWjCEj1owhI9aMISPWjCEj1owhI9aMISP - WjCEj1owhI9aMKOPWjCjj1owo49aMKOPWjCjj1owo49aMKOPWjCjj1owto9aMLaPWjC2j1owto9aMLaP - WjC2j1owto9aMLaPWjDJj1owyY9aMMmPWjDJj1owyY9aMMmPWjDJj1owyY9aMNqPWjDaj1ow2o9aMNqP - WjDaj1ow2o9aMNqPWjDaj1ow649aMOuPWjDrj1ow649aMOuPWjDrj1ow649aMOuPWjD6j1ow+o9aMPqP - WjD6j1ow+o9aMPqPWjD6j1ow+pRgOP+UYDj/lGA4/5RgOP+UYDj/lGA4/5RgOP+UYDj/mWhA/5loQP+Z - aED/mWhA/5loQP+ZaED/mWhA/5loQP+ic07/onNO/6JzTv+ic07/onNO/6JzTv+ic07/onNO/6yBXv+s - gV7/rIFe/6yBXv+sgV7/rIFe/6yBXv+sgV7/j1ow2Y9aMNmPWjDZj1ow2Y9aMNmPWjDZj1ow2Y9aMNmP - WjA0j1owNI9aMDSPWjA0j1owNI9aMDSPWjA0j1owNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPWjAUj1owFI9aMBSPWjAUj1owFI9aMBSP - WjAUj1owFI9aMISPWjCEj1owhI9aMISPWjCEj1owhI9aMISPWjCEj1owo49aMKOPWjCjj1owo49aMKOP - WjCjj1owo49aMKOPWjC2j1owto9aMLaPWjC2j1owto9aMLaPWjC2j1owto9aMMmPWjDJj1owyY9aMMmP - WjDJj1owyY9aMMmPWjDJj1ow2o9aMNqPWjDaj1ow2o9aMNqPWjDaj1ow2o9aMNqPWjDrj1ow649aMOuP - WjDrj1ow649aMOuPWjDrj1ow649aMPqPWjD6j1ow+o9aMPqPWjD6j1ow+o9aMPqPWjD6lGA4/5RgOP+U - YDj/lGA4/5RgOP+UYDj/lGA4/5RgOP+ZaED/mWhA/5loQP+ZaED/mWhA/5loQP+ZaED/mWhA/6JzTv+i - c07/onNO/6JzTv+ic07/onNO/6JzTv+ic07/rIFe/6yBXv+sgV7/rIFe/6yBXv+sgV7/rIFe/6yBXv+P - WjDZj1ow2Y9aMNmPWjDZj1ow2Y9aMNmPWjDZj1ow2Y9aMDSPWjA0j1owNI9aMDSPWjA0j1owNI9aMDSP - WjA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAI9aMBSPWjAUj1owFI9aMBSPWjAUj1owFI9aMBSPWjAUj1owhI9aMISPWjCEj1owhI9aMISP - WjCEj1owhI9aMISPWjCjj1owo49aMKOPWjCjj1owo49aMKOPWjCjj1owo49aMLaPWjC2j1owto9aMLaP - WjC2j1owto9aMLaPWjC2j1owyY9aMMmPWjDJj1owyY9aMMmPWjDJj1owyY9aMMmPWjDaj1ow2o9aMNqP - WjDaj1ow2o9aMNqPWjDaj1ow2o9aMOuPWjDrj1ow649aMOuPWjDrj1ow649aMOuPWjDrj1ow+o9aMPqP - WjD6j1ow+o9aMPqPWjD6j1ow+o9aMPqUYDj/lGA4/5RgOP+UYDj/lGA4/5RgOP+UYDj/lGA4/5loQP+Z - aED/mWhA/5loQP+ZaED/mWhA/5loQP+ZaED/onNO/6JzTv+ic07/onNO/6JzTv+ic07/onNO/6JzTv+s - gV7/rIFe/6yBXv+sgV7/rIFe/6yBXv+sgV7/rIFe/49aMNmPWjDZj1ow2Y9aMNmPWjDZj1ow2Y9aMNmP - WjDZj1owNI9aMDSPWjA0j1owNI9aMDSPWjA0j1owNI9aMDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj1owFI9aMBSPWjAUj1owFI9aMBSP - WjAUj1owFI9aMBSPWjCEj1owhI9aMISPWjCEj1owhI9aMISPWjCEj1owhI9aMKOPWjCjj1owo49aMKOP - WjCjj1owo49aMKOPWjCjj1owto9aMLaPWjC2j1owto9aMLaPWjC2j1owto9aMLaPWjDJj1owyY9aMMmP - WjDJj1owyY9aMMmPWjDJj1owyY9aMNqPWjDaj1ow2o9aMNqPWjDaj1ow2o9aMNqPWjDaj1ow649aMOuP - WjDrj1ow649aMOuPWjDrj1ow649aMOuPWjD6j1ow+o9aMPqPWjD6j1ow+o9aMPqPWjD6j1ow+pRgOP+U - YDj/lGA4/5RgOP+UYDj/lGA4/5RgOP+UYDj/mWhA/5loQP+ZaED/mWhA/5loQP+ZaED/mWhA/5loQP+i - c07/onNO/6JzTv+ic07/onNO/6JzTv+ic07/onNO/6yBXv+sgV7/rIFe/6yBXv+sgV7/rIFe/6yBXv+s - gV7/j1ow2Y9aMNmPWjDZj1ow2Y9aMNmPWjDZj1ow2Y9aMNmPWjA0j1owNI9aMDSPWjA0j1owNI9aMDSP - WjA0j1owNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAACPWjAUj1owFI9aMBSPWjAUj1owFI9aMBSPWjAUj1owFI9aMISPWjCEj1owhI9aMISP - WjCEj1owhI9aMISPWjCEj1owo49aMKOPWjCjj1owo49aMKOPWjCjj1owo49aMKOPWjC2j1owto9aMLaP - WjC2j1owto9aMLaPWjC2j1owto9aMMmPWjDJj1owyY9aMMmPWjDJj1owyY9aMMmPWjDJj1ow2o9aMNqP - WjDaj1ow2o9aMNqPWjDaj1ow2o9aMNqPWjDrj1ow649aMOuPWjDrj1ow649aMOuPWjDrj1ow649aMPqP - WjD6j1ow+o9aMPqPWjD6j1ow+o9aMPqPWjD6lGA4/5RgOP+UYDj/lGA4/5RgOP+UYDj/lGA4/5RgOP+Z - aED/mWhA/5loQP+ZaED/mWhA/5loQP+ZaED/mWhA/6JzTv+ic07/onNO/6JzTv+ic07/onNO/6JzTv+i - c07/rIFe/6yBXv+sgV7/rIFe/6yBXv+sgV7/rIFe/6yBXv+PWjDZj1ow2Y9aMNmPWjDZj1ow2Y9aMNmP - WjDZj1ow2Y9aMDSPWjA0j1owNI9aMDSPWjA0j1owNI9aMDSPWjA0AAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9aMBSPWjAUj1owFI9aMBSP - WjAUj1owFI9aMBSPWjAUj1owhI9aMISPWjCEj1owhI9aMISPWjCEj1owhI9aMISPWjCjj1owo49aMKOP - WjCjj1owo49aMKOPWjCjj1owo49aMLaPWjC2j1owto9aMLaPWjC2j1owto9aMLaPWjC2j1owyY9aMMmP - WjDJj1owyY9aMMmPWjDJj1owyY9aMMmPWjDaj1ow2o9aMNqPWjDaj1ow2o9aMNqPWjDaj1ow2o9aMOuP - WjDrj1ow649aMOuPWjDrj1ow649aMOuPWjDrj1ow+o9aMPqPWjD6j1ow+o9aMPqPWjD6j1ow+o9aMPqU - YDj/lGA4/5RgOP+UYDj/lGA4/5RgOP+UYDj/lGA4/5loQP+ZaED/mWhA/5loQP+ZaED/mWhA/5loQP+Z - aED/onNO/6JzTv+ic07/onNO/6JzTv+ic07/onNO/6JzTv+sgV7/rIFe/6yBXv+sgV7/rIFe/6yBXv+s - gV7/rIFe/49aMNmPWjDZj1ow2Y9aMNmPWjDZj1ow2Y9aMNmPWjDZj1owNI9aMDSPWjA0j1owNI9aMDSP - WjA0j1owNI9aMDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAj1owFI9aMBSPWjAUj1owFI9aMBSPWjAUj1owFI9aMBSPWjCEj1owhI9aMISP - WjCEj1owhI9aMISPWjCEj1owhI9aMKOPWjCjj1owo49aMKOPWjCjj1owo49aMKOPWjCjj1owto9aMLaP - WjC2j1owto9aMLaPWjC2j1owto9aMLaPWjDJj1owyY9aMMmPWjDJj1owyY9aMMmPWjDJj1owyY9aMNqP - WjDaj1ow2o9aMNqPWjDaj1ow2o9aMNqPWjDaj1ow649aMOuPWjDrj1ow649aMOuPWjDrj1ow649aMOuP - WjD6j1ow+o9aMPqPWjD6j1ow+o9aMPqPWjD6j1ow+pRgOP+UYDj/lGA4/5RgOP+UYDj/lGA4/5RgOP+U - YDj/mWhA/5loQP+ZaED/mWhA/5loQP+ZaED/mWhA/5loQP+ic07/onNO/6JzTv+ic07/onNO/6JzTv+i - c07/onNO/6yBXv+sgV7/rIFe/6yBXv+sgV7/rIFe/6yBXv+sgV7/j1ow2Y9aMNmPWjDZj1ow2Y9aMNmP - WjDZj1ow2Y9aMNmPWjA0j1owNI9aMDSPWjA0j1owNI9aMDSPWjA0j1owNAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPWjAUj1owFI9aMBSP - WjAUj1owFI9aMBSPWjAUj1owFI9aMISPWjCEj1owhI9aMISPWjCEj1owhI9aMISPWjCEj1owo49aMKOP - WjCjj1owo49aMKOPWjCjj1owo49aMKOPWjC2j1owto9aMLaPWjC2j1owto9aMLaPWjC2j1owto9aMMmP - WjDJj1owyY9aMMmPWjDJj1owyY9aMMmPWjDJj1ow2o9aMNqPWjDaj1ow2o9aMNqPWjDaj1ow2o9aMNqP - WjDrj1ow649aMOuPWjDrj1ow649aMOuPWjDrj1ow649aMPqPWjD6j1ow+o9aMPqPWjD6j1ow+o9aMPqP - WjD6lGA4/5RgOP+UYDj/lGA4/5RgOP+UYDj/lGA4/5RgOP+ZaED/mWhA/5loQP+ZaED/mWhA/5loQP+Z - aED/mWhA/6JzTv+ic07/onNO/6JzTv+ic07/onNO/6JzTv+ic07/rIFe/6yBXv+sgV7/rIFe/6yBXv+s - gV7/rIFe/6yBXv+PWjDZj1ow2Y9aMNmPWjDZj1ow2Y9aMNmPWjDZj1ow2Y9aMDSPWjA0j1owNI9aMDSP - WjA0j1owNI9aMDSPWjA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAJNeMmiTXjJok14yaJNeMmiTXjJok14yaJNeMmiTXjJot49s/7ePbP+3 - j2z/t49s/7ePbP+3j2z/t49s/7ePbP/WuaL/1rmi/9a5ov/WuaL/1rmi/9a5ov/WuaL/1rmi/9/Fsv/f - xbL/38Wy/9/Fsv/fxbL/38Wy/9/Fsv/fxbL/59TC/+fUwv/n1ML/59TC/+fUwv/n1ML/59TC/+fUwv/u - 39P/7t/T/+7f0//u39P/7t/T/+7f0//u39P/7t/T//Xq4v/16uL/9eri//Xq4v/16uL/9eri//Xq4v/1 - 6uL/+/Tv//v07//79O//+/Tv//v07//79O//+/Tv//v07//9+vb//fr2//369v/9+vb//fr2//369v/9 - +vb//fr2///+/f///v3///79///+/f///v3///79///+/f///v3/++vf//vr3//769//++vf//vr3//7 - 69//++vf//vr3//77+b/++/m//vv5v/77+b/++/m//vv5v/77+b/++/m/8Ccf//AnH//wJx//8Ccf//A - nH//wJx//8Ccf//AnH//k14yb5NeMm+TXjJvk14yb5NeMm+TXjJvk14yb5NeMm8AAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAk14yaJNeMmiT - XjJok14yaJNeMmiTXjJok14yaJNeMmi3j2z/t49s/7ePbP+3j2z/t49s/7ePbP+3j2z/t49s/9a5ov/W - uaL/1rmi/9a5ov/WuaL/1rmi/9a5ov/WuaL/38Wy/9/Fsv/fxbL/38Wy/9/Fsv/fxbL/38Wy/9/Fsv/n - 1ML/59TC/+fUwv/n1ML/59TC/+fUwv/n1ML/59TC/+7f0//u39P/7t/T/+7f0//u39P/7t/T/+7f0//u - 39P/9eri//Xq4v/16uL/9eri//Xq4v/16uL/9eri//Xq4v/79O//+/Tv//v07//79O//+/Tv//v07//7 - 9O//+/Tv//369v/9+vb//fr2//369v/9+vb//fr2//369v/9+vb///79///+/f///v3///79///+/f// - /v3///79///+/f/769//++vf//vr3//769//++vf//vr3//769//++vf//vv5v/77+b/++/m//vv5v/7 - 7+b/++/m//vv5v/77+b/wJx//8Ccf//AnH//wJx//8Ccf//AnH//wJx//8Ccf/+TXjJvk14yb5NeMm+T - XjJvk14yb5NeMm+TXjJvk14ybwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACTXjJok14yaJNeMmiTXjJok14yaJNeMmiTXjJok14yaLePbP+3 - j2z/t49s/7ePbP+3j2z/t49s/7ePbP+3j2z/1rmi/9a5ov/WuaL/1rmi/9a5ov/WuaL/1rmi/9a5ov/f - xbL/38Wy/9/Fsv/fxbL/38Wy/9/Fsv/fxbL/38Wy/+fUwv/n1ML/59TC/+fUwv/n1ML/59TC/+fUwv/n - 1ML/7t/T/+7f0//u39P/7t/T/+7f0//u39P/7t/T/+7f0//16uL/9eri//Xq4v/16uL/9eri//Xq4v/1 - 6uL/9eri//v07//79O//+/Tv//v07//79O//+/Tv//v07//79O///fr2//369v/9+vb//fr2//369v/9 - +vb//fr2//369v///v3///79///+/f///v3///79///+/f///v3///79//vr3//769//++vf//vr3//7 - 69//++vf//vr3//769//++/m//vv5v/77+b/++/m//vv5v/77+b/++/m//vv5v/AnH//wJx//8Ccf//A - nH//wJx//8Ccf//AnH//wJx//5NeMm+TXjJvk14yb5NeMm+TXjJvk14yb5NeMm+TXjJvAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJNeMmiT - XjJok14yaJNeMmiTXjJok14yaJNeMmiTXjJot49s/7ePbP+3j2z/t49s/7ePbP+3j2z/t49s/7ePbP/W - uaL/1rmi/9a5ov/WuaL/1rmi/9a5ov/WuaL/1rmi/9/Fsv/fxbL/38Wy/9/Fsv/fxbL/38Wy/9/Fsv/f - xbL/59TC/+fUwv/n1ML/59TC/+fUwv/n1ML/59TC/+fUwv/u39P/7t/T/+7f0//u39P/7t/T/+7f0//u - 39P/7t/T//Xq4v/16uL/9eri//Xq4v/16uL/9eri//Xq4v/16uL/+/Tv//v07//79O//+/Tv//v07//7 - 9O//+/Tv//v07//9+vb//fr2//369v/9+vb//fr2//369v/9+vb//fr2///+/f///v3///79///+/f// - /v3///79///+/f///v3/++vf//vr3//769//++vf//vr3//769//++vf//vr3//77+b/++/m//vv5v/7 - 7+b/++/m//vv5v/77+b/++/m/8Ccf//AnH//wJx//8Ccf//AnH//wJx//8Ccf//AnH//k14yb5NeMm+T - XjJvk14yb5NeMm+TXjJvk14yb5NeMm8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAk14yaJNeMmiTXjJok14yaJNeMmiTXjJok14yaJNeMmi3 - j2z/t49s/7ePbP+3j2z/t49s/7ePbP+3j2z/t49s/9a5ov/WuaL/1rmi/9a5ov/WuaL/1rmi/9a5ov/W - uaL/38Wy/9/Fsv/fxbL/38Wy/9/Fsv/fxbL/38Wy/9/Fsv/n1ML/59TC/+fUwv/n1ML/59TC/+fUwv/n - 1ML/59TC/+7f0//u39P/7t/T/+7f0//u39P/7t/T/+7f0//u39P/9eri//Xq4v/16uL/9eri//Xq4v/1 - 6uL/9eri//Xq4v/79O//+/Tv//v07//79O//+/Tv//v07//79O//+/Tv//369v/9+vb//fr2//369v/9 - +vb//fr2//369v/9+vb///79///+/f///v3///79///+/f///v3///79///+/f/769//++vf//vr3//7 - 69//++vf//vr3//769//++vf//vv5v/77+b/++/m//vv5v/77+b/++/m//vv5v/77+b/wJx//8Ccf//A - nH//wJx//8Ccf//AnH//wJx//8Ccf/+TXjJvk14yb5NeMm+TXjJvk14yb5NeMm+TXjJvk14ybwAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACT - XjJok14yaJNeMmiTXjJok14yaJNeMmiTXjJok14yaLePbP+3j2z/t49s/7ePbP+3j2z/t49s/7ePbP+3 - j2z/1rmi/9a5ov/WuaL/1rmi/9a5ov/WuaL/1rmi/9a5ov/fxbL/38Wy/9/Fsv/fxbL/38Wy/9/Fsv/f - xbL/38Wy/+fUwv/n1ML/59TC/+fUwv/n1ML/59TC/+fUwv/n1ML/7t/T/+7f0//u39P/7t/T/+7f0//u - 39P/7t/T/+7f0//16uL/9eri//Xq4v/16uL/9eri//Xq4v/16uL/9eri//v07//79O//+/Tv//v07//7 - 9O//+/Tv//v07//79O///fr2//369v/9+vb//fr2//369v/9+vb//fr2//369v///v3///79///+/f// - /v3///79///+/f///v3///79//vr3//769//++vf//vr3//769//++vf//vr3//769//++/m//vv5v/7 - 7+b/++/m//vv5v/77+b/++/m//vv5v/AnH//wJx//8Ccf//AnH//wJx//8Ccf//AnH//wJx//5NeMm+T - XjJvk14yb5NeMm+TXjJvk14yb5NeMm+TXjJvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJNeMmiTXjJok14yaJNeMmiTXjJok14yaJNeMmiT - XjJot49s/7ePbP+3j2z/t49s/7ePbP+3j2z/t49s/7ePbP/WuaL/1rmi/9a5ov/WuaL/1rmi/9a5ov/W - uaL/1rmi/9/Fsv/fxbL/38Wy/9/Fsv/fxbL/38Wy/9/Fsv/fxbL/59TC/+fUwv/n1ML/59TC/+fUwv/n - 1ML/59TC/+fUwv/u39P/7t/T/+7f0//u39P/7t/T/+7f0//u39P/7t/T//Xq4v/16uL/9eri//Xq4v/1 - 6uL/9eri//Xq4v/16uL/+/Tv//v07//79O//+/Tv//v07//79O//+/Tv//v07//9+vb//fr2//369v/9 - +vb//fr2//369v/9+vb//fr2///+/f///v3///79///+/f///v3///79///+/f///v3/++vf//vr3//7 - 69//++vf//vr3//769//++vf//vr3//77+b/++/m//vv5v/77+b/++/m//vv5v/77+b/++/m/8Ccf//A - nH//wJx//8Ccf//AnH//wJx//8Ccf//AnH//k14yb5NeMm+TXjJvk14yb5NeMm+TXjJvk14yb5NeMm8A - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAk14yaJNeMmiTXjJok14yaJNeMmiTXjJok14yaJNeMmi3j2z/t49s/7ePbP+3j2z/t49s/7ePbP+3 - j2z/t49s/9a5ov/WuaL/1rmi/9a5ov/WuaL/1rmi/9a5ov/WuaL/38Wy/9/Fsv/fxbL/38Wy/9/Fsv/f - xbL/38Wy/9/Fsv/n1ML/59TC/+fUwv/n1ML/59TC/+fUwv/n1ML/59TC/+7f0//u39P/7t/T/+7f0//u - 39P/7t/T/+7f0//u39P/9eri//Xq4v/16uL/9eri//Xq4v/16uL/9eri//Xq4v/79O//+/Tv//v07//7 - 9O//+/Tv//v07//79O//+/Tv//369v/9+vb//fr2//369v/9+vb//fr2//369v/9+vb///79///+/f// - /v3///79///+/f///v3///79///+/f/769//++vf//vr3//769//++vf//vr3//769//++vf//vv5v/7 - 7+b/++/m//vv5v/77+b/++/m//vv5v/77+b/wJx//8Ccf//AnH//wJx//8Ccf//AnH//wJx//8Ccf/+T - XjJvk14yb5NeMm+TXjJvk14yb5NeMm+TXjJvk14ybwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYYzWJmGM1iZhjNYmYYzWJmGM1iZhjNYmY - YzWJmGM1icejhP/Ho4T/x6OE/8ejhP/Ho4T/x6OE/8ejhP/Ho4T///////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////vz///78///+/P// - /vz///78///+/P///vz///78//779//++/f//vv3//779//++/f//vv3//779//++/f//vfx//738f/+ - 9/H//vfx//738f/+9/H//vfx//738f/+9vH//vbx//728f/+9vH//vbx//728f/+9vH//vbx/+Sthf/k - rYX/5K2F/+Sthf/krYX/5K2F/+Sthf/krYX/+ujb//ro2//66Nv/+ujb//ro2//66Nv/+ujb//ro2//O - rpT/zq6U/86ulP/OrpT/zq6U/86ulP/OrpT/zq6U/5hjNYuYYzWLmGM1i5hjNYuYYzWLmGM1i5hjNYuY - YzWLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAJhjNYmYYzWJmGM1iZhjNYmYYzWJmGM1iZhjNYmYYzWJx6OE/8ejhP/Ho4T/x6OE/8ejhP/H - o4T/x6OE/8ejhP////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - ///////////////////////////+/P///vz///78///+/P///vz///78///+/P///vz//vv3//779//+ - +/f//vv3//779//++/f//vv3//779//+9/H//vfx//738f/+9/H//vfx//738f/+9/H//vfx//728f/+ - 9vH//vbx//728f/+9vH//vbx//728f/+9vH/5K2F/+Sthf/krYX/5K2F/+Sthf/krYX/5K2F/+Sthf/6 - 6Nv/+ujb//ro2//66Nv/+ujb//ro2//66Nv/+ujb/86ulP/OrpT/zq6U/86ulP/OrpT/zq6U/86ulP/O - rpT/mGM1i5hjNYuYYzWLmGM1i5hjNYuYYzWLmGM1i5hjNYsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmGM1iZhjNYmYYzWJmGM1iZhjNYmY - YzWJmGM1iZhjNYnHo4T/x6OE/8ejhP/Ho4T/x6OE/8ejhP/Ho4T/x6OE//////////////////////// - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////78///+/P// - /vz///78///+/P///vz///78///+/P/++/f//vv3//779//++/f//vv3//779//++/f//vv3//738f/+ - 9/H//vfx//738f/+9/H//vfx//738f/+9/H//vbx//728f/+9vH//vbx//728f/+9vH//vbx//728f/k - rYX/5K2F/+Sthf/krYX/5K2F/+Sthf/krYX/5K2F//ro2//66Nv/+ujb//ro2//66Nv/+ujb//ro2//6 - 6Nv/zq6U/86ulP/OrpT/zq6U/86ulP/OrpT/zq6U/86ulP+YYzWLmGM1i5hjNYuYYzWLmGM1i5hjNYuY - YzWLmGM1iwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAACYYzWJmGM1iZhjNYmYYzWJmGM1iZhjNYmYYzWJmGM1icejhP/Ho4T/x6OE/8ejhP/H - o4T/x6OE/8ejhP/Ho4T///////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////vz///78///+/P///vz///78///+/P///vz///78//779//+ - +/f//vv3//779//++/f//vv3//779//++/f//vfx//738f/+9/H//vfx//738f/+9/H//vfx//738f/+ - 9vH//vbx//728f/+9vH//vbx//728f/+9vH//vbx/+Sthf/krYX/5K2F/+Sthf/krYX/5K2F/+Sthf/k - rYX/+ujb//ro2//66Nv/+ujb//ro2//66Nv/+ujb//ro2//OrpT/zq6U/86ulP/OrpT/zq6U/86ulP/O - rpT/zq6U/5hjNYuYYzWLmGM1i5hjNYuYYzWLmGM1i5hjNYuYYzWLAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJhjNYmYYzWJmGM1iZhjNYmY - YzWJmGM1iZhjNYmYYzWJx6OE/8ejhP/Ho4T/x6OE/8ejhP/Ho4T/x6OE/8ejhP////////////////// - //////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////+/P// - /vz///78///+/P///vz///78///+/P///vz//vv3//779//++/f//vv3//779//++/f//vv3//779//+ - 9/H//vfx//738f/+9/H//vfx//738f/+9/H//vfx//728f/+9vH//vbx//728f/+9vH//vbx//728f/+ - 9vH/5K2F/+Sthf/krYX/5K2F/+Sthf/krYX/5K2F/+Sthf/66Nv/+ujb//ro2//66Nv/+ujb//ro2//6 - 6Nv/+ujb/86ulP/OrpT/zq6U/86ulP/OrpT/zq6U/86ulP/OrpT/mGM1i5hjNYuYYzWLmGM1i5hjNYuY - YzWLmGM1i5hjNYsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAmGM1iZhjNYmYYzWJmGM1iZhjNYmYYzWJmGM1iZhjNYnHo4T/x6OE/8ejhP/H - o4T/x6OE/8ejhP/Ho4T/x6OE//////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////78///+/P///vz///78///+/P///vz///78///+/P/+ - +/f//vv3//779//++/f//vv3//779//++/f//vv3//738f/+9/H//vfx//738f/+9/H//vfx//738f/+ - 9/H//vbx//728f/+9vH//vbx//728f/+9vH//vbx//728f/krYX/5K2F/+Sthf/krYX/5K2F/+Sthf/k - rYX/5K2F//ro2//66Nv/+ujb//ro2//66Nv/+ujb//ro2//66Nv/zq6U/86ulP/OrpT/zq6U/86ulP/O - rpT/zq6U/86ulP+YYzWLmGM1i5hjNYuYYzWLmGM1i5hjNYuYYzWLmGM1iwAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYYzWJmGM1iZhjNYmY - YzWJmGM1iZhjNYmYYzWJmGM1icejhP/Ho4T/x6OE/8ejhP/Ho4T/x6OE/8ejhP/Ho4T///////////// - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - /vz///78///+/P///vz///78///+/P///vz///78//779//++/f//vv3//779//++/f//vv3//779//+ - +/f//vfx//738f/+9/H//vfx//738f/+9/H//vfx//738f/+9vH//vbx//728f/+9vH//vbx//728f/+ - 9vH//vbx/+Sthf/krYX/5K2F/+Sthf/krYX/5K2F/+Sthf/krYX/+ujb//ro2//66Nv/+ujb//ro2//6 - 6Nv/+ujb//ro2//OrpT/zq6U/86ulP/OrpT/zq6U/86ulP/OrpT/zq6U/5hjNYuYYzWLmGM1i5hjNYuY - YzWLmGM1i5hjNYuYYzWLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAJhjNYmYYzWJmGM1iZhjNYmYYzWJmGM1iZhjNYmYYzWJx6OE/8ejhP/H - o4T/x6OE/8ejhP/Ho4T/x6OE/8ejhP////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////////////////+/P///vz///78///+/P///vz///78///+/P// - /vz//vv3//779//++/f//vv3//779//++/f//vv3//779//+9/H//vfx//738f/+9/H//vfx//738f/+ - 9/H//vfx//728f/+9vH//vbx//728f/+9vH//vbx//728f/+9vH/5K2F/+Sthf/krYX/5K2F/+Sthf/k - rYX/5K2F/+Sthf/66Nv/+ujb//ro2//66Nv/+ujb//ro2//66Nv/+ujb/86ulP/OrpT/zq6U/86ulP/O - rpT/zq6U/86ulP/OrpT/mGM1i5hjNYuYYzWLmGM1i5hjNYuYYzWLmGM1i5hjNYsAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnWg4V51oOFed - aDhXnWg4V51oOFedaDhXnWg4V51oOFedaDj2nWg49p1oOPadaDj2nWg49p1oOPadaDj2nWg49rOEWP+z - hFj/s4RY/7OEWP+zhFj/s4RY/7OEWP+zhFj/2aR6/9mkev/ZpHr/2aR6/9mkev/ZpHr/2aR6/9mkev/Y - nW7/2J1u/9idbv/YnW7/2J1u/9idbv/YnW7/2J1u/9eaaf/Xmmn/15pp/9eaaf/Xmmn/15pp/9eaaf/X - mmn/2JVi/9iVYv/YlWL/2JVi/9iVYv/YlWL/2JVi/9iVYv/WkVz/1pFc/9aRXP/WkVz/1pFc/9aRXP/W - kVz/1pFc/9SOWP/Ujlj/1I5Y/9SOWP/Ujlj/1I5Y/9SOWP/Ujlj/041W/9ONVv/TjVb/041W/9ONVv/T - jVb/041W/9ONVv/inGj/4pxo/+KcaP/inGj/4pxo/+KcaP/inGj/4pxo//rj0f/649H/+uPR//rj0f/6 - 49H/+uPR//rj0f/649H/2Lqh/9i6of/YuqH/2Lqh/9i6of/YuqH/2Lqh/9i6of+daDienWg4np1oOJ6d - aDienWg4np1oOJ6daDienWg4ngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACdaDhXnWg4V51oOFedaDhXnWg4V51oOFedaDhXnWg4V51oOPad - aDj2nWg49p1oOPadaDj2nWg49p1oOPadaDj2s4RY/7OEWP+zhFj/s4RY/7OEWP+zhFj/s4RY/7OEWP/Z - pHr/2aR6/9mkev/ZpHr/2aR6/9mkev/ZpHr/2aR6/9idbv/YnW7/2J1u/9idbv/YnW7/2J1u/9idbv/Y - nW7/15pp/9eaaf/Xmmn/15pp/9eaaf/Xmmn/15pp/9eaaf/YlWL/2JVi/9iVYv/YlWL/2JVi/9iVYv/Y - lWL/2JVi/9aRXP/WkVz/1pFc/9aRXP/WkVz/1pFc/9aRXP/WkVz/1I5Y/9SOWP/Ujlj/1I5Y/9SOWP/U - jlj/1I5Y/9SOWP/TjVb/041W/9ONVv/TjVb/041W/9ONVv/TjVb/041W/+KcaP/inGj/4pxo/+KcaP/i - nGj/4pxo/+KcaP/inGj/+uPR//rj0f/649H/+uPR//rj0f/649H/+uPR//rj0f/YuqH/2Lqh/9i6of/Y - uqH/2Lqh/9i6of/YuqH/2Lqh/51oOJ6daDienWg4np1oOJ6daDienWg4np1oOJ6daDieAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ1oOFed - aDhXnWg4V51oOFedaDhXnWg4V51oOFedaDhXnWg49p1oOPadaDj2nWg49p1oOPadaDj2nWg49p1oOPaz - hFj/s4RY/7OEWP+zhFj/s4RY/7OEWP+zhFj/s4RY/9mkev/ZpHr/2aR6/9mkev/ZpHr/2aR6/9mkev/Z - pHr/2J1u/9idbv/YnW7/2J1u/9idbv/YnW7/2J1u/9idbv/Xmmn/15pp/9eaaf/Xmmn/15pp/9eaaf/X - mmn/15pp/9iVYv/YlWL/2JVi/9iVYv/YlWL/2JVi/9iVYv/YlWL/1pFc/9aRXP/WkVz/1pFc/9aRXP/W - kVz/1pFc/9aRXP/Ujlj/1I5Y/9SOWP/Ujlj/1I5Y/9SOWP/Ujlj/1I5Y/9ONVv/TjVb/041W/9ONVv/T - jVb/041W/9ONVv/TjVb/4pxo/+KcaP/inGj/4pxo/+KcaP/inGj/4pxo/+KcaP/649H/+uPR//rj0f/6 - 49H/+uPR//rj0f/649H/+uPR/9i6of/YuqH/2Lqh/9i6of/YuqH/2Lqh/9i6of/YuqH/nWg4np1oOJ6d - aDienWg4np1oOJ6daDienWg4np1oOJ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnWg4V51oOFedaDhXnWg4V51oOFedaDhXnWg4V51oOFed - aDj2nWg49p1oOPadaDj2nWg49p1oOPadaDj2nWg49rOEWP+zhFj/s4RY/7OEWP+zhFj/s4RY/7OEWP+z - hFj/2aR6/9mkev/ZpHr/2aR6/9mkev/ZpHr/2aR6/9mkev/YnW7/2J1u/9idbv/YnW7/2J1u/9idbv/Y - nW7/2J1u/9eaaf/Xmmn/15pp/9eaaf/Xmmn/15pp/9eaaf/Xmmn/2JVi/9iVYv/YlWL/2JVi/9iVYv/Y - lWL/2JVi/9iVYv/WkVz/1pFc/9aRXP/WkVz/1pFc/9aRXP/WkVz/1pFc/9SOWP/Ujlj/1I5Y/9SOWP/U - jlj/1I5Y/9SOWP/Ujlj/041W/9ONVv/TjVb/041W/9ONVv/TjVb/041W/9ONVv/inGj/4pxo/+KcaP/i - nGj/4pxo/+KcaP/inGj/4pxo//rj0f/649H/+uPR//rj0f/649H/+uPR//rj0f/649H/2Lqh/9i6of/Y - uqH/2Lqh/9i6of/YuqH/2Lqh/9i6of+daDienWg4np1oOJ6daDienWg4np1oOJ6daDienWg4ngAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACd - aDhXnWg4V51oOFedaDhXnWg4V51oOFedaDhXnWg4V51oOPadaDj2nWg49p1oOPadaDj2nWg49p1oOPad - aDj2s4RY/7OEWP+zhFj/s4RY/7OEWP+zhFj/s4RY/7OEWP/ZpHr/2aR6/9mkev/ZpHr/2aR6/9mkev/Z - pHr/2aR6/9idbv/YnW7/2J1u/9idbv/YnW7/2J1u/9idbv/YnW7/15pp/9eaaf/Xmmn/15pp/9eaaf/X - mmn/15pp/9eaaf/YlWL/2JVi/9iVYv/YlWL/2JVi/9iVYv/YlWL/2JVi/9aRXP/WkVz/1pFc/9aRXP/W - kVz/1pFc/9aRXP/WkVz/1I5Y/9SOWP/Ujlj/1I5Y/9SOWP/Ujlj/1I5Y/9SOWP/TjVb/041W/9ONVv/T - jVb/041W/9ONVv/TjVb/041W/+KcaP/inGj/4pxo/+KcaP/inGj/4pxo/+KcaP/inGj/+uPR//rj0f/6 - 49H/+uPR//rj0f/649H/+uPR//rj0f/YuqH/2Lqh/9i6of/YuqH/2Lqh/9i6of/YuqH/2Lqh/51oOJ6d - aDienWg4np1oOJ6daDienWg4np1oOJ6daDieAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ1oOFedaDhXnWg4V51oOFedaDhXnWg4V51oOFed - aDhXnWg49p1oOPadaDj2nWg49p1oOPadaDj2nWg49p1oOPazhFj/s4RY/7OEWP+zhFj/s4RY/7OEWP+z - hFj/s4RY/9mkev/ZpHr/2aR6/9mkev/ZpHr/2aR6/9mkev/ZpHr/2J1u/9idbv/YnW7/2J1u/9idbv/Y - nW7/2J1u/9idbv/Xmmn/15pp/9eaaf/Xmmn/15pp/9eaaf/Xmmn/15pp/9iVYv/YlWL/2JVi/9iVYv/Y - lWL/2JVi/9iVYv/YlWL/1pFc/9aRXP/WkVz/1pFc/9aRXP/WkVz/1pFc/9aRXP/Ujlj/1I5Y/9SOWP/U - jlj/1I5Y/9SOWP/Ujlj/1I5Y/9ONVv/TjVb/041W/9ONVv/TjVb/041W/9ONVv/TjVb/4pxo/+KcaP/i - nGj/4pxo/+KcaP/inGj/4pxo/+KcaP/649H/+uPR//rj0f/649H/+uPR//rj0f/649H/+uPR/9i6of/Y - uqH/2Lqh/9i6of/YuqH/2Lqh/9i6of/YuqH/nWg4np1oOJ6daDienWg4np1oOJ6daDienWg4np1oOJ4A - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAnWg4V51oOFedaDhXnWg4V51oOFedaDhXnWg4V51oOFedaDj2nWg49p1oOPadaDj2nWg49p1oOPad - aDj2nWg49rOEWP+zhFj/s4RY/7OEWP+zhFj/s4RY/7OEWP+zhFj/2aR6/9mkev/ZpHr/2aR6/9mkev/Z - pHr/2aR6/9mkev/YnW7/2J1u/9idbv/YnW7/2J1u/9idbv/YnW7/2J1u/9eaaf/Xmmn/15pp/9eaaf/X - mmn/15pp/9eaaf/Xmmn/2JVi/9iVYv/YlWL/2JVi/9iVYv/YlWL/2JVi/9iVYv/WkVz/1pFc/9aRXP/W - kVz/1pFc/9aRXP/WkVz/1pFc/9SOWP/Ujlj/1I5Y/9SOWP/Ujlj/1I5Y/9SOWP/Ujlj/041W/9ONVv/T - jVb/041W/9ONVv/TjVb/041W/9ONVv/inGj/4pxo/+KcaP/inGj/4pxo/+KcaP/inGj/4pxo//rj0f/6 - 49H/+uPR//rj0f/649H/+uPR//rj0f/649H/2Lqh/9i6of/YuqH/2Lqh/9i6of/YuqH/2Lqh/9i6of+d - aDienWg4np1oOJ6daDienWg4np1oOJ6daDienWg4ngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACdaDhXnWg4V51oOFedaDhXnWg4V51oOFed - aDhXnWg4V51oOPadaDj2nWg49p1oOPadaDj2nWg49p1oOPadaDj2s4RY/7OEWP+zhFj/s4RY/7OEWP+z - hFj/s4RY/7OEWP/ZpHr/2aR6/9mkev/ZpHr/2aR6/9mkev/ZpHr/2aR6/9idbv/YnW7/2J1u/9idbv/Y - nW7/2J1u/9idbv/YnW7/15pp/9eaaf/Xmmn/15pp/9eaaf/Xmmn/15pp/9eaaf/YlWL/2JVi/9iVYv/Y - lWL/2JVi/9iVYv/YlWL/2JVi/9aRXP/WkVz/1pFc/9aRXP/WkVz/1pFc/9aRXP/WkVz/1I5Y/9SOWP/U - jlj/1I5Y/9SOWP/Ujlj/1I5Y/9SOWP/TjVb/041W/9ONVv/TjVb/041W/9ONVv/TjVb/041W/+KcaP/i - nGj/4pxo/+KcaP/inGj/4pxo/+KcaP/inGj/+uPR//rj0f/649H/+uPR//rj0f/649H/+uPR//rj0f/Y - uqH/2Lqh/9i6of/YuqH/2Lqh/9i6of/YuqH/2Lqh/51oOJ6daDienWg4np1oOJ6daDienWg4np1oOJ6d - aDieAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAKNuOxSjbjsUo247FKNuOxSjbjsUo247FKNuOxSjbjsUo247q6NuO6ujbjuro247q6NuO6uj - bjuro247q6NuO6vVrYv/1a2L/9Wti//VrYv/1a2L/9Wti//VrYv/1a2L//3w5f/98OX//fDl//3w5f/9 - 8OX//fDl//3w5f/98OX/98eh//fHof/3x6H/98eh//fHof/3x6H/98eh//fHof/3z6z/98+s//fPrP/3 - z6z/98+s//fPrP/3z6z/98+s//nVtP/51bT/+dW0//nVtP/51bT/+dW0//nVtP/51bT/+Nq8//javP/4 - 2rz/+Nq8//javP/42rz/+Nq8//javP/43sH/+N7B//jewf/43sH/+N7B//jewf/43sH/+N7B//rhxf/6 - 4cX/+uHF//rhxf/64cX/+uHF//rhxf/64cX/+uTM//rkzP/65Mz/+uTM//rkzP/65Mz/+uTM//rkzP/9 - 9ez//fXs//317P/99ez//fXs//317P/99ez//fXs/+LOuf/izrn/4s65/+LOuf/izrn/4s65/+LOuf/i - zrn/o247s6NuO7Ojbjuzo247s6NuO7Ojbjuzo247s6NuO7MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo247FKNuOxSjbjsUo247FKNuOxSj - bjsUo247FKNuOxSjbjuro247q6NuO6ujbjuro247q6NuO6ujbjuro247q9Wti//VrYv/1a2L/9Wti//V - rYv/1a2L/9Wti//VrYv//fDl//3w5f/98OX//fDl//3w5f/98OX//fDl//3w5f/3x6H/98eh//fHof/3 - x6H/98eh//fHof/3x6H/98eh//fPrP/3z6z/98+s//fPrP/3z6z/98+s//fPrP/3z6z/+dW0//nVtP/5 - 1bT/+dW0//nVtP/51bT/+dW0//nVtP/42rz/+Nq8//javP/42rz/+Nq8//javP/42rz/+Nq8//jewf/4 - 3sH/+N7B//jewf/43sH/+N7B//jewf/43sH/+uHF//rhxf/64cX/+uHF//rhxf/64cX/+uHF//rhxf/6 - 5Mz/+uTM//rkzP/65Mz/+uTM//rkzP/65Mz/+uTM//317P/99ez//fXs//317P/99ez//fXs//317P/9 - 9ez/4s65/+LOuf/izrn/4s65/+LOuf/izrn/4s65/+LOuf+jbjuzo247s6NuO7Ojbjuzo247s6NuO7Oj - bjuzo247swAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAACjbjsUo247FKNuOxSjbjsUo247FKNuOxSjbjsUo247FKNuO6ujbjuro247q6NuO6uj - bjuro247q6NuO6ujbjur1a2L/9Wti//VrYv/1a2L/9Wti//VrYv/1a2L/9Wti//98OX//fDl//3w5f/9 - 8OX//fDl//3w5f/98OX//fDl//fHof/3x6H/98eh//fHof/3x6H/98eh//fHof/3x6H/98+s//fPrP/3 - z6z/98+s//fPrP/3z6z/98+s//fPrP/51bT/+dW0//nVtP/51bT/+dW0//nVtP/51bT/+dW0//javP/4 - 2rz/+Nq8//javP/42rz/+Nq8//javP/42rz/+N7B//jewf/43sH/+N7B//jewf/43sH/+N7B//jewf/6 - 4cX/+uHF//rhxf/64cX/+uHF//rhxf/64cX/+uHF//rkzP/65Mz/+uTM//rkzP/65Mz/+uTM//rkzP/6 - 5Mz//fXs//317P/99ez//fXs//317P/99ez//fXs//317P/izrn/4s65/+LOuf/izrn/4s65/+LOuf/i - zrn/4s65/6NuO7Ojbjuzo247s6NuO7Ojbjuzo247s6NuO7OjbjuzAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKNuOxSjbjsUo247FKNuOxSj - bjsUo247FKNuOxSjbjsUo247q6NuO6ujbjuro247q6NuO6ujbjuro247q6NuO6vVrYv/1a2L/9Wti//V - rYv/1a2L/9Wti//VrYv/1a2L//3w5f/98OX//fDl//3w5f/98OX//fDl//3w5f/98OX/98eh//fHof/3 - x6H/98eh//fHof/3x6H/98eh//fHof/3z6z/98+s//fPrP/3z6z/98+s//fPrP/3z6z/98+s//nVtP/5 - 1bT/+dW0//nVtP/51bT/+dW0//nVtP/51bT/+Nq8//javP/42rz/+Nq8//javP/42rz/+Nq8//javP/4 - 3sH/+N7B//jewf/43sH/+N7B//jewf/43sH/+N7B//rhxf/64cX/+uHF//rhxf/64cX/+uHF//rhxf/6 - 4cX/+uTM//rkzP/65Mz/+uTM//rkzP/65Mz/+uTM//rkzP/99ez//fXs//317P/99ez//fXs//317P/9 - 9ez//fXs/+LOuf/izrn/4s65/+LOuf/izrn/4s65/+LOuf/izrn/o247s6NuO7Ojbjuzo247s6NuO7Oj - bjuzo247s6NuO7MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAo247FKNuOxSjbjsUo247FKNuOxSjbjsUo247FKNuOxSjbjuro247q6NuO6uj - bjuro247q6NuO6ujbjuro247q9Wti//VrYv/1a2L/9Wti//VrYv/1a2L/9Wti//VrYv//fDl//3w5f/9 - 8OX//fDl//3w5f/98OX//fDl//3w5f/3x6H/98eh//fHof/3x6H/98eh//fHof/3x6H/98eh//fPrP/3 - z6z/98+s//fPrP/3z6z/98+s//fPrP/3z6z/+dW0//nVtP/51bT/+dW0//nVtP/51bT/+dW0//nVtP/4 - 2rz/+Nq8//javP/42rz/+Nq8//javP/42rz/+Nq8//jewf/43sH/+N7B//jewf/43sH/+N7B//jewf/4 - 3sH/+uHF//rhxf/64cX/+uHF//rhxf/64cX/+uHF//rhxf/65Mz/+uTM//rkzP/65Mz/+uTM//rkzP/6 - 5Mz/+uTM//317P/99ez//fXs//317P/99ez//fXs//317P/99ez/4s65/+LOuf/izrn/4s65/+LOuf/i - zrn/4s65/+LOuf+jbjuzo247s6NuO7Ojbjuzo247s6NuO7Ojbjuzo247swAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACjbjsUo247FKNuOxSj - bjsUo247FKNuOxSjbjsUo247FKNuO6ujbjuro247q6NuO6ujbjuro247q6NuO6ujbjur1a2L/9Wti//V - rYv/1a2L/9Wti//VrYv/1a2L/9Wti//98OX//fDl//3w5f/98OX//fDl//3w5f/98OX//fDl//fHof/3 - x6H/98eh//fHof/3x6H/98eh//fHof/3x6H/98+s//fPrP/3z6z/98+s//fPrP/3z6z/98+s//fPrP/5 - 1bT/+dW0//nVtP/51bT/+dW0//nVtP/51bT/+dW0//javP/42rz/+Nq8//javP/42rz/+Nq8//javP/4 - 2rz/+N7B//jewf/43sH/+N7B//jewf/43sH/+N7B//jewf/64cX/+uHF//rhxf/64cX/+uHF//rhxf/6 - 4cX/+uHF//rkzP/65Mz/+uTM//rkzP/65Mz/+uTM//rkzP/65Mz//fXs//317P/99ez//fXs//317P/9 - 9ez//fXs//317P/izrn/4s65/+LOuf/izrn/4s65/+LOuf/izrn/4s65/6NuO7Ojbjuzo247s6NuO7Oj - bjuzo247s6NuO7OjbjuzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAKNuOxSjbjsUo247FKNuOxSjbjsUo247FKNuOxSjbjsUo247q6NuO6uj - bjuro247q6NuO6ujbjuro247q6NuO6vVrYv/1a2L/9Wti//VrYv/1a2L/9Wti//VrYv/1a2L//3w5f/9 - 8OX//fDl//3w5f/98OX//fDl//3w5f/98OX/98eh//fHof/3x6H/98eh//fHof/3x6H/98eh//fHof/3 - z6z/98+s//fPrP/3z6z/98+s//fPrP/3z6z/98+s//nVtP/51bT/+dW0//nVtP/51bT/+dW0//nVtP/5 - 1bT/+Nq8//javP/42rz/+Nq8//javP/42rz/+Nq8//javP/43sH/+N7B//jewf/43sH/+N7B//jewf/4 - 3sH/+N7B//rhxf/64cX/+uHF//rhxf/64cX/+uHF//rhxf/64cX/+uTM//rkzP/65Mz/+uTM//rkzP/6 - 5Mz/+uTM//rkzP/99ez//fXs//317P/99ez//fXs//317P/99ez//fXs/+LOuf/izrn/4s65/+LOuf/i - zrn/4s65/+LOuf/izrn/o247s6NuO7Ojbjuzo247s6NuO7Ojbjuzo247s6NuO7MAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo247FKNuOxSj - bjsUo247FKNuOxSjbjsUo247FKNuOxSjbjuro247q6NuO6ujbjuro247q6NuO6ujbjuro247q9Wti//V - rYv/1a2L/9Wti//VrYv/1a2L/9Wti//VrYv//fDl//3w5f/98OX//fDl//3w5f/98OX//fDl//3w5f/3 - x6H/98eh//fHof/3x6H/98eh//fHof/3x6H/98eh//fPrP/3z6z/98+s//fPrP/3z6z/98+s//fPrP/3 - z6z/+dW0//nVtP/51bT/+dW0//nVtP/51bT/+dW0//nVtP/42rz/+Nq8//javP/42rz/+Nq8//javP/4 - 2rz/+Nq8//jewf/43sH/+N7B//jewf/43sH/+N7B//jewf/43sH/+uHF//rhxf/64cX/+uHF//rhxf/6 - 4cX/+uHF//rhxf/65Mz/+uTM//rkzP/65Mz/+uTM//rkzP/65Mz/+uTM//317P/99ez//fXs//317P/9 - 9ez//fXs//317P/99ez/4s65/+LOuf/izrn/4s65/+LOuf/izrn/4s65/+LOuf+jbjuzo247s6NuO7Oj - bjuzo247s6NuO7Ojbjuzo247swAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKl0Pyip - dD8oqXQ/KKl0PyipdD8oqXQ/KKl0PyipdD8otoVV/7aFVf+2hVX/toVV/7aFVf+2hVX/toVV/7aFVf/+ - /v3//v79//7+/f/+/v3//v79//7+/f/+/v3//v79//rewf/63sH/+t7B//rewf/63sH/+t7B//rewf/6 - 3sH/+ty+//rcvv/63L7/+ty+//rcvv/63L7/+ty+//rcvv/527//+du///nbv//527//+du///nbv//5 - 27//+du///nbv//527//+du///nbv//527//+du///nbv//527//+d3A//ndwP/53cD/+d3A//ndwP/5 - 3cD/+d3A//ndwP/627//+tu///rbv//627//+tu///rbv//627//+tu///rcwv/63ML/+tzC//rcwv/6 - 3ML/+tzC//rcwv/63ML//eve//3r3v/9697//eve//3r3v/9697//eve//3r3v/s3M3/7NzN/+zczf/s - 3M3/7NzN/+zczf/s3M3/7NzN/6l0P8qpdD/KqXQ/yql0P8qpdD/KqXQ/yql0P8qpdD/KAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqXQ/KKl0PyipdD8oqXQ/KKl0PyipdD8oqXQ/KKl0Pyi2 - hVX/toVV/7aFVf+2hVX/toVV/7aFVf+2hVX/toVV//7+/f/+/v3//v79//7+/f/+/v3//v79//7+/f/+ - /v3/+t7B//rewf/63sH/+t7B//rewf/63sH/+t7B//rewf/63L7/+ty+//rcvv/63L7/+ty+//rcvv/6 - 3L7/+ty+//nbv//527//+du///nbv//527//+du///nbv//527//+du///nbv//527//+du///nbv//5 - 27//+du///nbv//53cD/+d3A//ndwP/53cD/+d3A//ndwP/53cD/+d3A//rbv//627//+tu///rbv//6 - 27//+tu///rbv//627//+tzC//rcwv/63ML/+tzC//rcwv/63ML/+tzC//rcwv/9697//eve//3r3v/9 - 697//eve//3r3v/9697//eve/+zczf/s3M3/7NzN/+zczf/s3M3/7NzN/+zczf/s3M3/qXQ/yql0P8qp - dD/KqXQ/yql0P8qpdD/KqXQ/yql0P8oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACp - dD8oqXQ/KKl0PyipdD8oqXQ/KKl0PyipdD8oqXQ/KLaFVf+2hVX/toVV/7aFVf+2hVX/toVV/7aFVf+2 - hVX//v79//7+/f/+/v3//v79//7+/f/+/v3//v79//7+/f/63sH/+t7B//rewf/63sH/+t7B//rewf/6 - 3sH/+t7B//rcvv/63L7/+ty+//rcvv/63L7/+ty+//rcvv/63L7/+du///nbv//527//+du///nbv//5 - 27//+du///nbv//527//+du///nbv//527//+du///nbv//527//+du///ndwP/53cD/+d3A//ndwP/5 - 3cD/+d3A//ndwP/53cD/+tu///rbv//627//+tu///rbv//627//+tu///rbv//63ML/+tzC//rcwv/6 - 3ML/+tzC//rcwv/63ML/+tzC//3r3v/9697//eve//3r3v/9697//eve//3r3v/9697/7NzN/+zczf/s - 3M3/7NzN/+zczf/s3M3/7NzN/+zczf+pdD/KqXQ/yql0P8qpdD/KqXQ/yql0P8qpdD/KqXQ/ygAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKl0PyipdD8oqXQ/KKl0PyipdD8oqXQ/KKl0Pyip - dD8otoVV/7aFVf+2hVX/toVV/7aFVf+2hVX/toVV/7aFVf/+/v3//v79//7+/f/+/v3//v79//7+/f/+ - /v3//v79//rewf/63sH/+t7B//rewf/63sH/+t7B//rewf/63sH/+ty+//rcvv/63L7/+ty+//rcvv/6 - 3L7/+ty+//rcvv/527//+du///nbv//527//+du///nbv//527//+du///nbv//527//+du///nbv//5 - 27//+du///nbv//527//+d3A//ndwP/53cD/+d3A//ndwP/53cD/+d3A//ndwP/627//+tu///rbv//6 - 27//+tu///rbv//627//+tu///rcwv/63ML/+tzC//rcwv/63ML/+tzC//rcwv/63ML//eve//3r3v/9 - 697//eve//3r3v/9697//eve//3r3v/s3M3/7NzN/+zczf/s3M3/7NzN/+zczf/s3M3/7NzN/6l0P8qp - dD/KqXQ/yql0P8qpdD/KqXQ/yql0P8qpdD/KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAqXQ/KKl0PyipdD8oqXQ/KKl0PyipdD8oqXQ/KKl0Pyi2hVX/toVV/7aFVf+2hVX/toVV/7aFVf+2 - hVX/toVV//7+/f/+/v3//v79//7+/f/+/v3//v79//7+/f/+/v3/+t7B//rewf/63sH/+t7B//rewf/6 - 3sH/+t7B//rewf/63L7/+ty+//rcvv/63L7/+ty+//rcvv/63L7/+ty+//nbv//527//+du///nbv//5 - 27//+du///nbv//527//+du///nbv//527//+du///nbv//527//+du///nbv//53cD/+d3A//ndwP/5 - 3cD/+d3A//ndwP/53cD/+d3A//rbv//627//+tu///rbv//627//+tu///rbv//627//+tzC//rcwv/6 - 3ML/+tzC//rcwv/63ML/+tzC//rcwv/9697//eve//3r3v/9697//eve//3r3v/9697//eve/+zczf/s - 3M3/7NzN/+zczf/s3M3/7NzN/+zczf/s3M3/qXQ/yql0P8qpdD/KqXQ/yql0P8qpdD/KqXQ/yql0P8oA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACpdD8oqXQ/KKl0PyipdD8oqXQ/KKl0Pyip - dD8oqXQ/KLaFVf+2hVX/toVV/7aFVf+2hVX/toVV/7aFVf+2hVX//v79//7+/f/+/v3//v79//7+/f/+ - /v3//v79//7+/f/63sH/+t7B//rewf/63sH/+t7B//rewf/63sH/+t7B//rcvv/63L7/+ty+//rcvv/6 - 3L7/+ty+//rcvv/63L7/+du///nbv//527//+du///nbv//527//+du///nbv//527//+du///nbv//5 - 27//+du///nbv//527//+du///ndwP/53cD/+d3A//ndwP/53cD/+d3A//ndwP/53cD/+tu///rbv//6 - 27//+tu///rbv//627//+tu///rbv//63ML/+tzC//rcwv/63ML/+tzC//rcwv/63ML/+tzC//3r3v/9 - 697//eve//3r3v/9697//eve//3r3v/9697/7NzN/+zczf/s3M3/7NzN/+zczf/s3M3/7NzN/+zczf+p - dD/KqXQ/yql0P8qpdD/KqXQ/yql0P8qpdD/KqXQ/ygAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAKl0PyipdD8oqXQ/KKl0PyipdD8oqXQ/KKl0PyipdD8otoVV/7aFVf+2hVX/toVV/7aFVf+2 - hVX/toVV/7aFVf/+/v3//v79//7+/f/+/v3//v79//7+/f/+/v3//v79//rewf/63sH/+t7B//rewf/6 - 3sH/+t7B//rewf/63sH/+ty+//rcvv/63L7/+ty+//rcvv/63L7/+ty+//rcvv/527//+du///nbv//5 - 27//+du///nbv//527//+du///nbv//527//+du///nbv//527//+du///nbv//527//+d3A//ndwP/5 - 3cD/+d3A//ndwP/53cD/+d3A//ndwP/627//+tu///rbv//627//+tu///rbv//627//+tu///rcwv/6 - 3ML/+tzC//rcwv/63ML/+tzC//rcwv/63ML//eve//3r3v/9697//eve//3r3v/9697//eve//3r3v/s - 3M3/7NzN/+zczf/s3M3/7NzN/+zczf/s3M3/7NzN/6l0P8qpdD/KqXQ/yql0P8qpdD/KqXQ/yql0P8qp - dD/KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqXQ/KKl0PyipdD8oqXQ/KKl0Pyip - dD8oqXQ/KKl0Pyi2hVX/toVV/7aFVf+2hVX/toVV/7aFVf+2hVX/toVV//7+/f/+/v3//v79//7+/f/+ - /v3//v79//7+/f/+/v3/+t7B//rewf/63sH/+t7B//rewf/63sH/+t7B//rewf/63L7/+ty+//rcvv/6 - 3L7/+ty+//rcvv/63L7/+ty+//nbv//527//+du///nbv//527//+du///nbv//527//+du///nbv//5 - 27//+du///nbv//527//+du///nbv//53cD/+d3A//ndwP/53cD/+d3A//ndwP/53cD/+d3A//rbv//6 - 27//+tu///rbv//627//+tu///rbv//627//+tzC//rcwv/63ML/+tzC//rcwv/63ML/+tzC//rcwv/9 - 697//eve//3r3v/9697//eve//3r3v/9697//eve/+zczf/s3M3/7NzN/+zczf/s3M3/7NzN/+zczf/s - 3M3/qXQ/yql0P8qpdD/KqXQ/yql0P8qpdD/KqXQ/yql0P8oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAACwekIesHpCHrB6Qh6wekIesHpCHrB6Qh6wekIesHpCHriFUf+4hVH/uIVR/7iFUf+4 - hVH/uIVR/7iFUf+4hVH//vz5//78+f/+/Pn//vz5//78+f/+/Pn//vz5//78+f/53L7/+dy+//ncvv/5 - 3L7/+dy+//ncvv/53L7/+dy+//jbvv/4277/+Nu+//jbvv/4277/+Nu+//jbvv/4277/+Ny///jcv//4 - 3L//+Ny///jcv//43L//+Ny///jcv//528H/+dvB//nbwf/528H/+dvB//nbwf/528H/+dvB//ncwP/5 - 3MD/+dzA//ncwP/53MD/+dzA//ncwP/53MD/+d3B//ndwf/53cH/+d3B//ndwf/53cH/+d3B//ndwf/6 - 3cL/+t3C//rdwv/63cL/+t3C//rdwv/63cL/+t3C//vn1P/759T/++fU//vn1P/759T/++fU//vn1P/7 - 59T/9e3i//Xt4v/17eL/9e3i//Xt4v/17eL/9e3i//Xt4v+wekLksHpC5LB6QuSwekLksHpC5LB6QuSw - ekLksHpC5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALB6Qh6wekIesHpCHrB6Qh6w - ekIesHpCHrB6Qh6wekIeuIVR/7iFUf+4hVH/uIVR/7iFUf+4hVH/uIVR/7iFUf/+/Pn//vz5//78+f/+ - /Pn//vz5//78+f/+/Pn//vz5//ncvv/53L7/+dy+//ncvv/53L7/+dy+//ncvv/53L7/+Nu+//jbvv/4 - 277/+Nu+//jbvv/4277/+Nu+//jbvv/43L//+Ny///jcv//43L//+Ny///jcv//43L//+Ny///nbwf/5 - 28H/+dvB//nbwf/528H/+dvB//nbwf/528H/+dzA//ncwP/53MD/+dzA//ncwP/53MD/+dzA//ncwP/5 - 3cH/+d3B//ndwf/53cH/+d3B//ndwf/53cH/+d3B//rdwv/63cL/+t3C//rdwv/63cL/+t3C//rdwv/6 - 3cL/++fU//vn1P/759T/++fU//vn1P/759T/++fU//vn1P/17eL/9e3i//Xt4v/17eL/9e3i//Xt4v/1 - 7eL/9e3i/7B6QuSwekLksHpC5LB6QuSwekLksHpC5LB6QuSwekLkAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAsHpCHrB6Qh6wekIesHpCHrB6Qh6wekIesHpCHrB6Qh64hVH/uIVR/7iFUf+4 - hVH/uIVR/7iFUf+4hVH/uIVR//78+f/+/Pn//vz5//78+f/+/Pn//vz5//78+f/+/Pn/+dy+//ncvv/5 - 3L7/+dy+//ncvv/53L7/+dy+//ncvv/4277/+Nu+//jbvv/4277/+Nu+//jbvv/4277/+Nu+//jcv//4 - 3L//+Ny///jcv//43L//+Ny///jcv//43L//+dvB//nbwf/528H/+dvB//nbwf/528H/+dvB//nbwf/5 - 3MD/+dzA//ncwP/53MD/+dzA//ncwP/53MD/+dzA//ndwf/53cH/+d3B//ndwf/53cH/+d3B//ndwf/5 - 3cH/+t3C//rdwv/63cL/+t3C//rdwv/63cL/+t3C//rdwv/759T/++fU//vn1P/759T/++fU//vn1P/7 - 59T/++fU//Xt4v/17eL/9e3i//Xt4v/17eL/9e3i//Xt4v/17eL/sHpC5LB6QuSwekLksHpC5LB6QuSw - ekLksHpC5LB6QuQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwekIesHpCHrB6Qh6w - ekIesHpCHrB6Qh6wekIesHpCHriFUf+4hVH/uIVR/7iFUf+4hVH/uIVR/7iFUf+4hVH//vz5//78+f/+ - /Pn//vz5//78+f/+/Pn//vz5//78+f/53L7/+dy+//ncvv/53L7/+dy+//ncvv/53L7/+dy+//jbvv/4 - 277/+Nu+//jbvv/4277/+Nu+//jbvv/4277/+Ny///jcv//43L//+Ny///jcv//43L//+Ny///jcv//5 - 28H/+dvB//nbwf/528H/+dvB//nbwf/528H/+dvB//ncwP/53MD/+dzA//ncwP/53MD/+dzA//ncwP/5 - 3MD/+d3B//ndwf/53cH/+d3B//ndwf/53cH/+d3B//ndwf/63cL/+t3C//rdwv/63cL/+t3C//rdwv/6 - 3cL/+t3C//vn1P/759T/++fU//vn1P/759T/++fU//vn1P/759T/9e3i//Xt4v/17eL/9e3i//Xt4v/1 - 7eL/9e3i//Xt4v+wekLksHpC5LB6QuSwekLksHpC5LB6QuSwekLksHpC5AAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAALB6Qh6wekIesHpCHrB6Qh6wekIesHpCHrB6Qh6wekIeuIVR/7iFUf+4 - hVH/uIVR/7iFUf+4hVH/uIVR/7iFUf/+/Pn//vz5//78+f/+/Pn//vz5//78+f/+/Pn//vz5//ncvv/5 - 3L7/+dy+//ncvv/53L7/+dy+//ncvv/53L7/+Nu+//jbvv/4277/+Nu+//jbvv/4277/+Nu+//jbvv/4 - 3L//+Ny///jcv//43L//+Ny///jcv//43L//+Ny///nbwf/528H/+dvB//nbwf/528H/+dvB//nbwf/5 - 28H/+dzA//ncwP/53MD/+dzA//ncwP/53MD/+dzA//ncwP/53cH/+d3B//ndwf/53cH/+d3B//ndwf/5 - 3cH/+d3B//rdwv/63cL/+t3C//rdwv/63cL/+t3C//rdwv/63cL/++fU//vn1P/759T/++fU//vn1P/7 - 59T/++fU//vn1P/17eL/9e3i//Xt4v/17eL/9e3i//Xt4v/17eL/9e3i/7B6QuSwekLksHpC5LB6QuSw - ekLksHpC5LB6QuSwekLkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsHpCHrB6Qh6w - ekIesHpCHrB6Qh6wekIesHpCHrB6Qh64hVH/uIVR/7iFUf+4hVH/uIVR/7iFUf+4hVH/uIVR//78+f/+ - /Pn//vz5//78+f/+/Pn//vz5//78+f/+/Pn/+dy+//ncvv/53L7/+dy+//ncvv/53L7/+dy+//ncvv/4 - 277/+Nu+//jbvv/4277/+Nu+//jbvv/4277/+Nu+//jcv//43L//+Ny///jcv//43L//+Ny///jcv//4 - 3L//+dvB//nbwf/528H/+dvB//nbwf/528H/+dvB//nbwf/53MD/+dzA//ncwP/53MD/+dzA//ncwP/5 - 3MD/+dzA//ndwf/53cH/+d3B//ndwf/53cH/+d3B//ndwf/53cH/+t3C//rdwv/63cL/+t3C//rdwv/6 - 3cL/+t3C//rdwv/759T/++fU//vn1P/759T/++fU//vn1P/759T/++fU//Xt4v/17eL/9e3i//Xt4v/1 - 7eL/9e3i//Xt4v/17eL/sHpC5LB6QuSwekLksHpC5LB6QuSwekLksHpC5LB6QuQAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwekIesHpCHrB6Qh6wekIesHpCHrB6Qh6wekIesHpCHriFUf+4 - hVH/uIVR/7iFUf+4hVH/uIVR/7iFUf+4hVH//vz5//78+f/+/Pn//vz5//78+f/+/Pn//vz5//78+f/5 - 3L7/+dy+//ncvv/53L7/+dy+//ncvv/53L7/+dy+//jbvv/4277/+Nu+//jbvv/4277/+Nu+//jbvv/4 - 277/+Ny///jcv//43L//+Ny///jcv//43L//+Ny///jcv//528H/+dvB//nbwf/528H/+dvB//nbwf/5 - 28H/+dvB//ncwP/53MD/+dzA//ncwP/53MD/+dzA//ncwP/53MD/+d3B//ndwf/53cH/+d3B//ndwf/5 - 3cH/+d3B//ndwf/63cL/+t3C//rdwv/63cL/+t3C//rdwv/63cL/+t3C//vn1P/759T/++fU//vn1P/7 - 59T/++fU//vn1P/759T/9e3i//Xt4v/17eL/9e3i//Xt4v/17eL/9e3i//Xt4v+wekLksHpC5LB6QuSw - ekLksHpC5LB6QuSwekLksHpC5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALB6Qh6w - ekIesHpCHrB6Qh6wekIesHpCHrB6Qh6wekIeuIVR/7iFUf+4hVH/uIVR/7iFUf+4hVH/uIVR/7iFUf/+ - /Pn//vz5//78+f/+/Pn//vz5//78+f/+/Pn//vz5//ncvv/53L7/+dy+//ncvv/53L7/+dy+//ncvv/5 - 3L7/+Nu+//jbvv/4277/+Nu+//jbvv/4277/+Nu+//jbvv/43L//+Ny///jcv//43L//+Ny///jcv//4 - 3L//+Ny///nbwf/528H/+dvB//nbwf/528H/+dvB//nbwf/528H/+dzA//ncwP/53MD/+dzA//ncwP/5 - 3MD/+dzA//ncwP/53cH/+d3B//ndwf/53cH/+d3B//ndwf/53cH/+d3B//rdwv/63cL/+t3C//rdwv/6 - 3cL/+t3C//rdwv/63cL/++fU//vn1P/759T/++fU//vn1P/759T/++fU//vn1P/17eL/9e3i//Xt4v/1 - 7eL/9e3i//Xt4v/17eL/9e3i/7B6QuSwekLksHpC5LB6QuSwekLksHpC5LB6QuSwekLkAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtoFGCbaBRgm2gUYJtoFGCbaBRgm2gUYJtoFGCbaBRgm4 - hEr/uIRK/7iESv+4hEr/uIRK/7iESv+4hEr/uIRK//779//++/f//vv3//779//++/f//vv3//779//+ - +/f/+dzA//ncwP/53MD/+dzA//ncwP/53MD/+dzA//ncwP/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/4 - 3L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Nu///jbv//427//+Nu///jbv//4 - 27//+Nu///jbv//53b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//5 - 3b//+d2///ndv//53b//+d3C//ndwv/53cL/+d3C//ndwv/53cL/+d3C//ndwv/74sv/++LL//viy//7 - 4sv/++LL//viy//74sv/++LL//z59f/8+fX//Pn1//z59f/8+fX//Pn1//z59f/8+fX/toFG+7aBRvu2 - gUb7toFG+7aBRvu2gUb7toFG+7aBRvu2gUYBtoFGAbaBRgG2gUYBtoFGAbaBRgG2gUYBtoFGAQAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC2 - gUYJtoFGCbaBRgm2gUYJtoFGCbaBRgm2gUYJtoFGCbiESv+4hEr/uIRK/7iESv+4hEr/uIRK/7iESv+4 - hEr//vv3//779//++/f//vv3//779//++/f//vv3//779//53MD/+dzA//ncwP/53MD/+dzA//ncwP/5 - 3MD/+dzA//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/4 - 3L7/+Ny+//jcvv/427//+Nu///jbv//427//+Nu///jbv//427//+Nu///ndv//53b//+d2///ndv//5 - 3b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//53cL/+d3C//ndwv/5 - 3cL/+d3C//ndwv/53cL/+d3C//viy//74sv/++LL//viy//74sv/++LL//viy//74sv//Pn1//z59f/8 - +fX//Pn1//z59f/8+fX//Pn1//z59f+2gUb7toFG+7aBRvu2gUb7toFG+7aBRvu2gUb7toFG+7aBRgG2 - gUYBtoFGAbaBRgG2gUYBtoFGAbaBRgG2gUYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALaBRgm2gUYJtoFGCbaBRgm2gUYJtoFGCbaBRgm2 - gUYJuIRK/7iESv+4hEr/uIRK/7iESv+4hEr/uIRK/7iESv/++/f//vv3//779//++/f//vv3//779//+ - +/f//vv3//ncwP/53MD/+dzA//ncwP/53MD/+dzA//ncwP/53MD/+Ny+//jcvv/43L7/+Ny+//jcvv/4 - 3L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jbv//427//+Nu///jbv//4 - 27//+Nu///jbv//427//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//5 - 3b//+d2///ndv//53b//+d2///ndwv/53cL/+d3C//ndwv/53cL/+d3C//ndwv/53cL/++LL//viy//7 - 4sv/++LL//viy//74sv/++LL//viy//8+fX//Pn1//z59f/8+fX//Pn1//z59f/8+fX//Pn1/7aBRvu2 - gUb7toFG+7aBRvu2gUb7toFG+7aBRvu2gUb7toFGAbaBRgG2gUYBtoFGAbaBRgG2gUYBtoFGAbaBRgEA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAtoFGCbaBRgm2gUYJtoFGCbaBRgm2gUYJtoFGCbaBRgm4hEr/uIRK/7iESv+4hEr/uIRK/7iESv+4 - hEr/uIRK//779//++/f//vv3//779//++/f//vv3//779//++/f/+dzA//ncwP/53MD/+dzA//ncwP/5 - 3MD/+dzA//ncwP/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/4 - 3L7/+Ny+//jcvv/43L7/+Nu///jbv//427//+Nu///jbv//427//+Nu///jbv//53b//+d2///ndv//5 - 3b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//53b//+d3C//ndwv/5 - 3cL/+d3C//ndwv/53cL/+d3C//ndwv/74sv/++LL//viy//74sv/++LL//viy//74sv/++LL//z59f/8 - +fX//Pn1//z59f/8+fX//Pn1//z59f/8+fX/toFG+7aBRvu2gUb7toFG+7aBRvu2gUb7toFG+7aBRvu2 - gUYBtoFGAbaBRgG2gUYBtoFGAbaBRgG2gUYBtoFGAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC2gUYJtoFGCbaBRgm2gUYJtoFGCbaBRgm2 - gUYJtoFGCbiESv+4hEr/uIRK/7iESv+4hEr/uIRK/7iESv+4hEr//vv3//779//++/f//vv3//779//+ - +/f//vv3//779//53MD/+dzA//ncwP/53MD/+dzA//ncwP/53MD/+dzA//jcvv/43L7/+Ny+//jcvv/4 - 3L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/427//+Nu///jbv//4 - 27//+Nu///jbv//427//+Nu///ndv//53b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//5 - 3b//+d2///ndv//53b//+d2///ndv//53cL/+d3C//ndwv/53cL/+d3C//ndwv/53cL/+d3C//viy//7 - 4sv/++LL//viy//74sv/++LL//viy//74sv//Pn1//z59f/8+fX//Pn1//z59f/8+fX//Pn1//z59f+2 - gUb7toFG+7aBRvu2gUb7toFG+7aBRvu2gUb7toFG+7aBRgG2gUYBtoFGAbaBRgG2gUYBtoFGAbaBRgG2 - gUYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAALaBRgm2gUYJtoFGCbaBRgm2gUYJtoFGCbaBRgm2gUYJuIRK/7iESv+4hEr/uIRK/7iESv+4 - hEr/uIRK/7iESv/++/f//vv3//779//++/f//vv3//779//++/f//vv3//ncwP/53MD/+dzA//ncwP/5 - 3MD/+dzA//ncwP/53MD/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/4 - 3L7/+Ny+//jcvv/43L7/+Ny+//jbv//427//+Nu///jbv//427//+Nu///jbv//427//+d2///ndv//5 - 3b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndwv/5 - 3cL/+d3C//ndwv/53cL/+d3C//ndwv/53cL/++LL//viy//74sv/++LL//viy//74sv/++LL//viy//8 - +fX//Pn1//z59f/8+fX//Pn1//z59f/8+fX//Pn1/7aBRvu2gUb7toFG+7aBRvu2gUb7toFG+7aBRvu2 - gUb7toFGAbaBRgG2gUYBtoFGAbaBRgG2gUYBtoFGAbaBRgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtoFGCbaBRgm2gUYJtoFGCbaBRgm2 - gUYJtoFGCbaBRgm4hEr/uIRK/7iESv+4hEr/uIRK/7iESv+4hEr/uIRK//779//++/f//vv3//779//+ - +/f//vv3//779//++/f/+dzA//ncwP/53MD/+dzA//ncwP/53MD/+dzA//ncwP/43L7/+Ny+//jcvv/4 - 3L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Nu///jbv//4 - 27//+Nu///jbv//427//+Nu///jbv//53b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//5 - 3b//+d2///ndv//53b//+d2///ndv//53b//+d3C//ndwv/53cL/+d3C//ndwv/53cL/+d3C//ndwv/7 - 4sv/++LL//viy//74sv/++LL//viy//74sv/++LL//z59f/8+fX//Pn1//z59f/8+fX//Pn1//z59f/8 - +fX/toFG+7aBRvu2gUb7toFG+7aBRvu2gUb7toFG+7aBRvu2gUYBtoFGAbaBRgG2gUYBtoFGAbaBRgG2 - gUYBtoFGAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAC2gUYJtoFGCbaBRgm2gUYJtoFGCbaBRgm2gUYJtoFGCbiESv+4hEr/uIRK/7iESv+4 - hEr/uIRK/7iESv+4hEr//vv3//779//++/f//vv3//779//++/f//vv3//779//53MD/+dzA//ncwP/5 - 3MD/+dzA//ncwP/53MD/+dzA//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/4 - 3L7/+Ny+//jcvv/43L7/+Ny+//jcvv/427//+Nu///jbv//427//+Nu///jbv//427//+Nu///ndv//5 - 3b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//5 - 3cL/+d3C//ndwv/53cL/+d3C//ndwv/53cL/+d3C//viy//74sv/++LL//viy//74sv/++LL//viy//7 - 4sv//Pn1//z59f/8+fX//Pn1//z59f/8+fX//Pn1//z59f+2gUb7toFG+7aBRvu2gUb7toFG+7aBRvu2 - gUb7toFG+7aBRgG2gUYBtoFGAbaBRgG2gUYBtoFGAbaBRgG2gUYBAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAvIdK+byHSvm8h0r5vIdK+byHSvm8h0r5vIdK+byHSvn89vD//Pbw//z28P/8 - 9vD//Pbw//z28P/89vD//Pbw//nfx//538f/+d/H//nfx//538f/+d/H//nfx//538f/+dy8//ncvP/5 - 3Lz/+dy8//ncvP/53Lz/+dy8//ncvP/63L7/+ty+//rcvv/63L7/+ty+//rcvv/63L7/+ty+//rbwP/6 - 28D/+tvA//rbwP/628D/+tvA//rbwP/628D/+t3C//rdwv/63cL/+t3C//rdwv/63cL/+t3C//rdwv/6 - 3cH/+t3B//rdwf/63cH/+t3B//rdwf/63cH/+t3B//ndw//53cP/+d3D//ndw//53cP/+d3D//ndw//5 - 3cP/++DJ//vgyf/74Mn/++DJ//vgyf/74Mn/++DJ//vgyf///Pr///z6///8+v///Pr///z6///8+v// - /Pr///z6/8CMUv/AjFL/wIxS/8CMUv/AjFL/wIxS/8CMUv/AjFL/vIdKD7yHSg+8h0oPvIdKD7yHSg+8 - h0oPvIdKD7yHSg8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8h0r5vIdK+byHSvm8 - h0r5vIdK+byHSvm8h0r5vIdK+fz28P/89vD//Pbw//z28P/89vD//Pbw//z28P/89vD/+d/H//nfx//5 - 38f/+d/H//nfx//538f/+d/H//nfx//53Lz/+dy8//ncvP/53Lz/+dy8//ncvP/53Lz/+dy8//rcvv/6 - 3L7/+ty+//rcvv/63L7/+ty+//rcvv/63L7/+tvA//rbwP/628D/+tvA//rbwP/628D/+tvA//rbwP/6 - 3cL/+t3C//rdwv/63cL/+t3C//rdwv/63cL/+t3C//rdwf/63cH/+t3B//rdwf/63cH/+t3B//rdwf/6 - 3cH/+d3D//ndw//53cP/+d3D//ndw//53cP/+d3D//ndw//74Mn/++DJ//vgyf/74Mn/++DJ//vgyf/7 - 4Mn/++DJ///8+v///Pr///z6///8+v///Pr///z6///8+v///Pr/wIxS/8CMUv/AjFL/wIxS/8CMUv/A - jFL/wIxS/8CMUv+8h0oPvIdKD7yHSg+8h0oPvIdKD7yHSg+8h0oPvIdKDwAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAALyHSvm8h0r5vIdK+byHSvm8h0r5vIdK+byHSvm8h0r5/Pbw//z28P/8 - 9vD//Pbw//z28P/89vD//Pbw//z28P/538f/+d/H//nfx//538f/+d/H//nfx//538f/+d/H//ncvP/5 - 3Lz/+dy8//ncvP/53Lz/+dy8//ncvP/53Lz/+ty+//rcvv/63L7/+ty+//rcvv/63L7/+ty+//rcvv/6 - 28D/+tvA//rbwP/628D/+tvA//rbwP/628D/+tvA//rdwv/63cL/+t3C//rdwv/63cL/+t3C//rdwv/6 - 3cL/+t3B//rdwf/63cH/+t3B//rdwf/63cH/+t3B//rdwf/53cP/+d3D//ndw//53cP/+d3D//ndw//5 - 3cP/+d3D//vgyf/74Mn/++DJ//vgyf/74Mn/++DJ//vgyf/74Mn///z6///8+v///Pr///z6///8+v// - /Pr///z6///8+v/AjFL/wIxS/8CMUv/AjFL/wIxS/8CMUv/AjFL/wIxS/7yHSg+8h0oPvIdKD7yHSg+8 - h0oPvIdKD7yHSg+8h0oPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvIdK+byHSvm8 - h0r5vIdK+byHSvm8h0r5vIdK+byHSvn89vD//Pbw//z28P/89vD//Pbw//z28P/89vD//Pbw//nfx//5 - 38f/+d/H//nfx//538f/+d/H//nfx//538f/+dy8//ncvP/53Lz/+dy8//ncvP/53Lz/+dy8//ncvP/6 - 3L7/+ty+//rcvv/63L7/+ty+//rcvv/63L7/+ty+//rbwP/628D/+tvA//rbwP/628D/+tvA//rbwP/6 - 28D/+t3C//rdwv/63cL/+t3C//rdwv/63cL/+t3C//rdwv/63cH/+t3B//rdwf/63cH/+t3B//rdwf/6 - 3cH/+t3B//ndw//53cP/+d3D//ndw//53cP/+d3D//ndw//53cP/++DJ//vgyf/74Mn/++DJ//vgyf/7 - 4Mn/++DJ//vgyf///Pr///z6///8+v///Pr///z6///8+v///Pr///z6/8CMUv/AjFL/wIxS/8CMUv/A - jFL/wIxS/8CMUv/AjFL/vIdKD7yHSg+8h0oPvIdKD7yHSg+8h0oPvIdKD7yHSg8AAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8h0r5vIdK+byHSvm8h0r5vIdK+byHSvm8h0r5vIdK+fz28P/8 - 9vD//Pbw//z28P/89vD//Pbw//z28P/89vD/+d/H//nfx//538f/+d/H//nfx//538f/+d/H//nfx//5 - 3Lz/+dy8//ncvP/53Lz/+dy8//ncvP/53Lz/+dy8//rcvv/63L7/+ty+//rcvv/63L7/+ty+//rcvv/6 - 3L7/+tvA//rbwP/628D/+tvA//rbwP/628D/+tvA//rbwP/63cL/+t3C//rdwv/63cL/+t3C//rdwv/6 - 3cL/+t3C//rdwf/63cH/+t3B//rdwf/63cH/+t3B//rdwf/63cH/+d3D//ndw//53cP/+d3D//ndw//5 - 3cP/+d3D//ndw//74Mn/++DJ//vgyf/74Mn/++DJ//vgyf/74Mn/++DJ///8+v///Pr///z6///8+v// - /Pr///z6///8+v///Pr/wIxS/8CMUv/AjFL/wIxS/8CMUv/AjFL/wIxS/8CMUv+8h0oPvIdKD7yHSg+8 - h0oPvIdKD7yHSg+8h0oPvIdKDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALyHSvm8 - h0r5vIdK+byHSvm8h0r5vIdK+byHSvm8h0r5/Pbw//z28P/89vD//Pbw//z28P/89vD//Pbw//z28P/5 - 38f/+d/H//nfx//538f/+d/H//nfx//538f/+d/H//ncvP/53Lz/+dy8//ncvP/53Lz/+dy8//ncvP/5 - 3Lz/+ty+//rcvv/63L7/+ty+//rcvv/63L7/+ty+//rcvv/628D/+tvA//rbwP/628D/+tvA//rbwP/6 - 28D/+tvA//rdwv/63cL/+t3C//rdwv/63cL/+t3C//rdwv/63cL/+t3B//rdwf/63cH/+t3B//rdwf/6 - 3cH/+t3B//rdwf/53cP/+d3D//ndw//53cP/+d3D//ndw//53cP/+d3D//vgyf/74Mn/++DJ//vgyf/7 - 4Mn/++DJ//vgyf/74Mn///z6///8+v///Pr///z6///8+v///Pr///z6///8+v/AjFL/wIxS/8CMUv/A - jFL/wIxS/8CMUv/AjFL/wIxS/7yHSg+8h0oPvIdKD7yHSg+8h0oPvIdKD7yHSg+8h0oPAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvIdK+byHSvm8h0r5vIdK+byHSvm8h0r5vIdK+byHSvn8 - 9vD//Pbw//z28P/89vD//Pbw//z28P/89vD//Pbw//nfx//538f/+d/H//nfx//538f/+d/H//nfx//5 - 38f/+dy8//ncvP/53Lz/+dy8//ncvP/53Lz/+dy8//ncvP/63L7/+ty+//rcvv/63L7/+ty+//rcvv/6 - 3L7/+ty+//rbwP/628D/+tvA//rbwP/628D/+tvA//rbwP/628D/+t3C//rdwv/63cL/+t3C//rdwv/6 - 3cL/+t3C//rdwv/63cH/+t3B//rdwf/63cH/+t3B//rdwf/63cH/+t3B//ndw//53cP/+d3D//ndw//5 - 3cP/+d3D//ndw//53cP/++DJ//vgyf/74Mn/++DJ//vgyf/74Mn/++DJ//vgyf///Pr///z6///8+v// - /Pr///z6///8+v///Pr///z6/8CMUv/AjFL/wIxS/8CMUv/AjFL/wIxS/8CMUv/AjFL/vIdKD7yHSg+8 - h0oPvIdKD7yHSg+8h0oPvIdKD7yHSg8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 - h0r5vIdK+byHSvm8h0r5vIdK+byHSvm8h0r5vIdK+fz28P/89vD//Pbw//z28P/89vD//Pbw//z28P/8 - 9vD/+d/H//nfx//538f/+d/H//nfx//538f/+d/H//nfx//53Lz/+dy8//ncvP/53Lz/+dy8//ncvP/5 - 3Lz/+dy8//rcvv/63L7/+ty+//rcvv/63L7/+ty+//rcvv/63L7/+tvA//rbwP/628D/+tvA//rbwP/6 - 28D/+tvA//rbwP/63cL/+t3C//rdwv/63cL/+t3C//rdwv/63cL/+t3C//rdwf/63cH/+t3B//rdwf/6 - 3cH/+t3B//rdwf/63cH/+d3D//ndw//53cP/+d3D//ndw//53cP/+d3D//ndw//74Mn/++DJ//vgyf/7 - 4Mn/++DJ//vgyf/74Mn/++DJ///8+v///Pr///z6///8+v///Pr///z6///8+v///Pr/wIxS/8CMUv/A - jFL/wIxS/8CMUv/AjFL/wIxS/8CMUv+8h0oPvIdKD7yHSg+8h0oPvIdKD7yHSg+8h0oPvIdKDwAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMONTdrDjU3aw41N2sONTdrDjU3aw41N2sONTdrD - jU3a9efY//Xn2P/159j/9efY//Xn2P/159j/9efY//Xn2P/65dL/+uXS//rl0v/65dL/+uXS//rl0v/6 - 5dL/+uXS//nau//52rv/+dq7//nau//52rv/+dq7//nau//52rv/+du7//nbu//527v/+du7//nbu//5 - 27v/+du7//nbu//6277/+tu+//rbvv/6277/+tu+//rbvv/6277/+tu+//rdwP/63cD/+t3A//rdwP/6 - 3cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/53cP/+d3D//ndw//5 - 3cP/+d3D//ndw//53cP/+d3D//vhyP/74cj/++HI//vhyP/74cj/++HI//vhyP/74cj///37///9+/// - /fv///37///9+////fv///37///9+//Ik1b/yJNW/8iTVv/Ik1b/yJNW/8iTVv/Ik1b/yJNW/8ONTRLD - jU0Sw41NEsONTRLDjU0Sw41NEsONTRLDjU0SAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAw41N2sONTdrDjU3aw41N2sONTdrDjU3aw41N2sONTdr159j/9efY//Xn2P/159j/9efY//Xn2P/1 - 59j/9efY//rl0v/65dL/+uXS//rl0v/65dL/+uXS//rl0v/65dL/+dq7//nau//52rv/+dq7//nau//5 - 2rv/+dq7//nau//527v/+du7//nbu//527v/+du7//nbu//527v/+du7//rbvv/6277/+tu+//rbvv/6 - 277/+tu+//rbvv/6277/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/6 - 3cD/+t3A//rdwP/63cD/+t3A//ndw//53cP/+d3D//ndw//53cP/+d3D//ndw//53cP/++HI//vhyP/7 - 4cj/++HI//vhyP/74cj/++HI//vhyP///fv///37///9+////fv///37///9+////fv///37/8iTVv/I - k1b/yJNW/8iTVv/Ik1b/yJNW/8iTVv/Ik1b/w41NEsONTRLDjU0Sw41NEsONTRLDjU0Sw41NEsONTRIA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDjU3aw41N2sONTdrDjU3aw41N2sONTdrD - jU3aw41N2vXn2P/159j/9efY//Xn2P/159j/9efY//Xn2P/159j/+uXS//rl0v/65dL/+uXS//rl0v/6 - 5dL/+uXS//rl0v/52rv/+dq7//nau//52rv/+dq7//nau//52rv/+dq7//nbu//527v/+du7//nbu//5 - 27v/+du7//nbu//527v/+tu+//rbvv/6277/+tu+//rbvv/6277/+tu+//rbvv/63cD/+t3A//rdwP/6 - 3cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+d3D//ndw//5 - 3cP/+d3D//ndw//53cP/+d3D//ndw//74cj/++HI//vhyP/74cj/++HI//vhyP/74cj/++HI///9+/// - /fv///37///9+////fv///37///9+////fv/yJNW/8iTVv/Ik1b/yJNW/8iTVv/Ik1b/yJNW/8iTVv/D - jU0Sw41NEsONTRLDjU0Sw41NEsONTRLDjU0Sw41NEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAMONTdrDjU3aw41N2sONTdrDjU3aw41N2sONTdrDjU3a9efY//Xn2P/159j/9efY//Xn2P/1 - 59j/9efY//Xn2P/65dL/+uXS//rl0v/65dL/+uXS//rl0v/65dL/+uXS//nau//52rv/+dq7//nau//5 - 2rv/+dq7//nau//52rv/+du7//nbu//527v/+du7//nbu//527v/+du7//nbu//6277/+tu+//rbvv/6 - 277/+tu+//rbvv/6277/+tu+//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/6 - 3cD/+t3A//rdwP/63cD/+t3A//rdwP/53cP/+d3D//ndw//53cP/+d3D//ndw//53cP/+d3D//vhyP/7 - 4cj/++HI//vhyP/74cj/++HI//vhyP/74cj///37///9+////fv///37///9+////fv///37///9+//I - k1b/yJNW/8iTVv/Ik1b/yJNW/8iTVv/Ik1b/yJNW/8ONTRLDjU0Sw41NEsONTRLDjU0Sw41NEsONTRLD - jU0SAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw41N2sONTdrDjU3aw41N2sONTdrD - jU3aw41N2sONTdr159j/9efY//Xn2P/159j/9efY//Xn2P/159j/9efY//rl0v/65dL/+uXS//rl0v/6 - 5dL/+uXS//rl0v/65dL/+dq7//nau//52rv/+dq7//nau//52rv/+dq7//nau//527v/+du7//nbu//5 - 27v/+du7//nbu//527v/+du7//rbvv/6277/+tu+//rbvv/6277/+tu+//rbvv/6277/+t3A//rdwP/6 - 3cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//ndw//5 - 3cP/+d3D//ndw//53cP/+d3D//ndw//53cP/++HI//vhyP/74cj/++HI//vhyP/74cj/++HI//vhyP// - /fv///37///9+////fv///37///9+////fv///37/8iTVv/Ik1b/yJNW/8iTVv/Ik1b/yJNW/8iTVv/I - k1b/w41NEsONTRLDjU0Sw41NEsONTRLDjU0Sw41NEsONTRIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAADDjU3aw41N2sONTdrDjU3aw41N2sONTdrDjU3aw41N2vXn2P/159j/9efY//Xn2P/1 - 59j/9efY//Xn2P/159j/+uXS//rl0v/65dL/+uXS//rl0v/65dL/+uXS//rl0v/52rv/+dq7//nau//5 - 2rv/+dq7//nau//52rv/+dq7//nbu//527v/+du7//nbu//527v/+du7//nbu//527v/+tu+//rbvv/6 - 277/+tu+//rbvv/6277/+tu+//rbvv/63cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/6 - 3cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+d3D//ndw//53cP/+d3D//ndw//53cP/+d3D//ndw//7 - 4cj/++HI//vhyP/74cj/++HI//vhyP/74cj/++HI///9+////fv///37///9+////fv///37///9+/// - /fv/yJNW/8iTVv/Ik1b/yJNW/8iTVv/Ik1b/yJNW/8iTVv/DjU0Sw41NEsONTRLDjU0Sw41NEsONTRLD - jU0Sw41NEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMONTdrDjU3aw41N2sONTdrD - jU3aw41N2sONTdrDjU3a9efY//Xn2P/159j/9efY//Xn2P/159j/9efY//Xn2P/65dL/+uXS//rl0v/6 - 5dL/+uXS//rl0v/65dL/+uXS//nau//52rv/+dq7//nau//52rv/+dq7//nau//52rv/+du7//nbu//5 - 27v/+du7//nbu//527v/+du7//nbu//6277/+tu+//rbvv/6277/+tu+//rbvv/6277/+tu+//rdwP/6 - 3cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/5 - 3cP/+d3D//ndw//53cP/+d3D//ndw//53cP/+d3D//vhyP/74cj/++HI//vhyP/74cj/++HI//vhyP/7 - 4cj///37///9+////fv///37///9+////fv///37///9+//Ik1b/yJNW/8iTVv/Ik1b/yJNW/8iTVv/I - k1b/yJNW/8ONTRLDjU0Sw41NEsONTRLDjU0Sw41NEsONTRLDjU0SAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAw41N2sONTdrDjU3aw41N2sONTdrDjU3aw41N2sONTdr159j/9efY//Xn2P/1 - 59j/9efY//Xn2P/159j/9efY//rl0v/65dL/+uXS//rl0v/65dL/+uXS//rl0v/65dL/+dq7//nau//5 - 2rv/+dq7//nau//52rv/+dq7//nau//527v/+du7//nbu//527v/+du7//nbu//527v/+du7//rbvv/6 - 277/+tu+//rbvv/6277/+tu+//rbvv/6277/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/6 - 3cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//ndw//53cP/+d3D//ndw//53cP/+d3D//ndw//5 - 3cP/++HI//vhyP/74cj/++HI//vhyP/74cj/++HI//vhyP///fv///37///9+////fv///37///9+/// - /fv///37/8iTVv/Ik1b/yJNW/8iTVv/Ik1b/yJNW/8iTVv/Ik1b/w41NEsONTRLDjU0Sw41NEsONTRLD - jU0Sw41NEsONTRIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADKk1G7ypNRu8qTUbvK - k1G7ypNRu8qTUbvKk1G7ypNRu/DZwP/w2cD/8NnA//DZwP/w2cD/8NnA//DZwP/w2cD/++3h//vt4f/7 - 7eH/++3h//vt4f/77eH/++3h//vt4f/52r//+dq///nav//52r//+dq///nav//52r//+dq///ncwf/5 - 3MH/+dzB//ncwf/53MH/+dzB//ncwf/53MH/+d7E//nexP/53sT/+d7E//nexP/53sT/+d7E//nexP/6 - 4Mf/+uDH//rgx//64Mf/+uDH//rgx//64Mf/+uDH//riyv/64sr/+uLK//riyv/64sr/+uLK//riyv/6 - 4sr/+uLN//rizf/64s3/+uLN//rizf/64s3/+uLN//rizf/65dD/+uXQ//rl0P/65dD/+uXQ//rl0P/6 - 5dD/+uXQ///+/f///v3///79///+/f///v3///79///+/f///v3/y45Z/8uOWf/Ljln/y45Z/8uOWf/L - jln/y45Z/8uOWf/Kk1HxypNR8cqTUfHKk1HxypNR8cqTUfHKk1HxypNR8cqTUUXKk1FFypNRRcqTUUXK - k1FFypNRRcqTUUXKk1FFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAMqTUbvKk1G7ypNRu8qTUbvKk1G7ypNRu8qTUbvKk1G78NnA//DZwP/w - 2cD/8NnA//DZwP/w2cD/8NnA//DZwP/77eH/++3h//vt4f/77eH/++3h//vt4f/77eH/++3h//nav//5 - 2r//+dq///nav//52r//+dq///nav//52r//+dzB//ncwf/53MH/+dzB//ncwf/53MH/+dzB//ncwf/5 - 3sT/+d7E//nexP/53sT/+d7E//nexP/53sT/+d7E//rgx//64Mf/+uDH//rgx//64Mf/+uDH//rgx//6 - 4Mf/+uLK//riyv/64sr/+uLK//riyv/64sr/+uLK//riyv/64s3/+uLN//rizf/64s3/+uLN//rizf/6 - 4s3/+uLN//rl0P/65dD/+uXQ//rl0P/65dD/+uXQ//rl0P/65dD///79///+/f///v3///79///+/f// - /v3///79///+/f/Ljln/y45Z/8uOWf/Ljln/y45Z/8uOWf/Ljln/y45Z/8qTUfHKk1HxypNR8cqTUfHK - k1HxypNR8cqTUfHKk1HxypNRRcqTUUXKk1FFypNRRcqTUUXKk1FFypNRRcqTUUUAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAypNRu8qTUbvK - k1G7ypNRu8qTUbvKk1G7ypNRu8qTUbvw2cD/8NnA//DZwP/w2cD/8NnA//DZwP/w2cD/8NnA//vt4f/7 - 7eH/++3h//vt4f/77eH/++3h//vt4f/77eH/+dq///nav//52r//+dq///nav//52r//+dq///nav//5 - 3MH/+dzB//ncwf/53MH/+dzB//ncwf/53MH/+dzB//nexP/53sT/+d7E//nexP/53sT/+d7E//nexP/5 - 3sT/+uDH//rgx//64Mf/+uDH//rgx//64Mf/+uDH//rgx//64sr/+uLK//riyv/64sr/+uLK//riyv/6 - 4sr/+uLK//rizf/64s3/+uLN//rizf/64s3/+uLN//rizf/64s3/+uXQ//rl0P/65dD/+uXQ//rl0P/6 - 5dD/+uXQ//rl0P///v3///79///+/f///v3///79///+/f///v3///79/8uOWf/Ljln/y45Z/8uOWf/L - jln/y45Z/8uOWf/Ljln/ypNR8cqTUfHKk1HxypNR8cqTUfHKk1HxypNR8cqTUfHKk1FFypNRRcqTUUXK - k1FFypNRRcqTUUXKk1FFypNRRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADKk1G7ypNRu8qTUbvKk1G7ypNRu8qTUbvKk1G7ypNRu/DZwP/w - 2cD/8NnA//DZwP/w2cD/8NnA//DZwP/w2cD/++3h//vt4f/77eH/++3h//vt4f/77eH/++3h//vt4f/5 - 2r//+dq///nav//52r//+dq///nav//52r//+dq///ncwf/53MH/+dzB//ncwf/53MH/+dzB//ncwf/5 - 3MH/+d7E//nexP/53sT/+d7E//nexP/53sT/+d7E//nexP/64Mf/+uDH//rgx//64Mf/+uDH//rgx//6 - 4Mf/+uDH//riyv/64sr/+uLK//riyv/64sr/+uLK//riyv/64sr/+uLN//rizf/64s3/+uLN//rizf/6 - 4s3/+uLN//rizf/65dD/+uXQ//rl0P/65dD/+uXQ//rl0P/65dD/+uXQ///+/f///v3///79///+/f// - /v3///79///+/f///v3/y45Z/8uOWf/Ljln/y45Z/8uOWf/Ljln/y45Z/8uOWf/Kk1HxypNR8cqTUfHK - k1HxypNR8cqTUfHKk1HxypNR8cqTUUXKk1FFypNRRcqTUUXKk1FFypNRRcqTUUXKk1FFAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMqTUbvK - k1G7ypNRu8qTUbvKk1G7ypNRu8qTUbvKk1G78NnA//DZwP/w2cD/8NnA//DZwP/w2cD/8NnA//DZwP/7 - 7eH/++3h//vt4f/77eH/++3h//vt4f/77eH/++3h//nav//52r//+dq///nav//52r//+dq///nav//5 - 2r//+dzB//ncwf/53MH/+dzB//ncwf/53MH/+dzB//ncwf/53sT/+d7E//nexP/53sT/+d7E//nexP/5 - 3sT/+d7E//rgx//64Mf/+uDH//rgx//64Mf/+uDH//rgx//64Mf/+uLK//riyv/64sr/+uLK//riyv/6 - 4sr/+uLK//riyv/64s3/+uLN//rizf/64s3/+uLN//rizf/64s3/+uLN//rl0P/65dD/+uXQ//rl0P/6 - 5dD/+uXQ//rl0P/65dD///79///+/f///v3///79///+/f///v3///79///+/f/Ljln/y45Z/8uOWf/L - jln/y45Z/8uOWf/Ljln/y45Z/8qTUfHKk1HxypNR8cqTUfHKk1HxypNR8cqTUfHKk1HxypNRRcqTUUXK - k1FFypNRRcqTUUXKk1FFypNRRcqTUUUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAypNRu8qTUbvKk1G7ypNRu8qTUbvKk1G7ypNRu8qTUbvw - 2cD/8NnA//DZwP/w2cD/8NnA//DZwP/w2cD/8NnA//vt4f/77eH/++3h//vt4f/77eH/++3h//vt4f/7 - 7eH/+dq///nav//52r//+dq///nav//52r//+dq///nav//53MH/+dzB//ncwf/53MH/+dzB//ncwf/5 - 3MH/+dzB//nexP/53sT/+d7E//nexP/53sT/+d7E//nexP/53sT/+uDH//rgx//64Mf/+uDH//rgx//6 - 4Mf/+uDH//rgx//64sr/+uLK//riyv/64sr/+uLK//riyv/64sr/+uLK//rizf/64s3/+uLN//rizf/6 - 4s3/+uLN//rizf/64s3/+uXQ//rl0P/65dD/+uXQ//rl0P/65dD/+uXQ//rl0P///v3///79///+/f// - /v3///79///+/f///v3///79/8uOWf/Ljln/y45Z/8uOWf/Ljln/y45Z/8uOWf/Ljln/ypNR8cqTUfHK - k1HxypNR8cqTUfHKk1HxypNR8cqTUfHKk1FFypNRRcqTUUXKk1FFypNRRcqTUUXKk1FFypNRRQAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADK - k1G7ypNRu8qTUbvKk1G7ypNRu8qTUbvKk1G7ypNRu/DZwP/w2cD/8NnA//DZwP/w2cD/8NnA//DZwP/w - 2cD/++3h//vt4f/77eH/++3h//vt4f/77eH/++3h//vt4f/52r//+dq///nav//52r//+dq///nav//5 - 2r//+dq///ncwf/53MH/+dzB//ncwf/53MH/+dzB//ncwf/53MH/+d7E//nexP/53sT/+d7E//nexP/5 - 3sT/+d7E//nexP/64Mf/+uDH//rgx//64Mf/+uDH//rgx//64Mf/+uDH//riyv/64sr/+uLK//riyv/6 - 4sr/+uLK//riyv/64sr/+uLN//rizf/64s3/+uLN//rizf/64s3/+uLN//rizf/65dD/+uXQ//rl0P/6 - 5dD/+uXQ//rl0P/65dD/+uXQ///+/f///v3///79///+/f///v3///79///+/f///v3/y45Z/8uOWf/L - jln/y45Z/8uOWf/Ljln/y45Z/8uOWf/Kk1HxypNR8cqTUfHKk1HxypNR8cqTUfHKk1HxypNR8cqTUUXK - k1FFypNRRcqTUUXKk1FFypNRRcqTUUXKk1FFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMqTUbvKk1G7ypNRu8qTUbvKk1G7ypNRu8qTUbvK - k1G78NnA//DZwP/w2cD/8NnA//DZwP/w2cD/8NnA//DZwP/77eH/++3h//vt4f/77eH/++3h//vt4f/7 - 7eH/++3h//nav//52r//+dq///nav//52r//+dq///nav//52r//+dzB//ncwf/53MH/+dzB//ncwf/5 - 3MH/+dzB//ncwf/53sT/+d7E//nexP/53sT/+d7E//nexP/53sT/+d7E//rgx//64Mf/+uDH//rgx//6 - 4Mf/+uDH//rgx//64Mf/+uLK//riyv/64sr/+uLK//riyv/64sr/+uLK//riyv/64s3/+uLN//rizf/6 - 4s3/+uLN//rizf/64s3/+uLN//rl0P/65dD/+uXQ//rl0P/65dD/+uXQ//rl0P/65dD///79///+/f// - /v3///79///+/f///v3///79///+/f/Ljln/y45Z/8uOWf/Ljln/y45Z/8uOWf/Ljln/y45Z/8qTUfHK - k1HxypNR8cqTUfHKk1HxypNR8cqTUfHKk1HxypNRRcqTUUXKk1FFypNRRcqTUUXKk1FFypNRRcqTUUUA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAA0JlUpNCZVKTQmVSk0JlUpNCZVKTQmVSk0JlUpNCZVKTt0LH/7dCx/+3Qsf/t0LH/7dCx/+3Qsf/t - 0LH/7dCx///28P//9vD///bw///28P//9vD///bw///28P//9vD/+uHK//rhyv/64cr/+uHK//rhyv/6 - 4cr/+uHK//rhyv/748z/++PM//vjzP/748z/++PM//vjzP/748z/++PM//vj0P/749D/++PQ//vj0P/7 - 49D/++PQ//vj0P/749D/++bT//vm0//75tP/++bT//vm0//75tP/++bT//vm0//76dX/++nV//vp1f/7 - 6dX/++nV//vp1f/76dX/++nV//zp2P/86dj//OnY//zp2P/86dj//OnY//zp2P/86dj//Orb//zq2//8 - 6tv//Orb//zq2//86tv//Orb//zq2/////3////9/////f////3////9/////f////3////9/9KccP/S - nHD/0pxw/9KccP/SnHD/0pxw/9KccP/SnHD/7tnA/+7ZwP/u2cD/7tnA/+7ZwP/u2cD/7tnA/+7ZwP/Q - mVTl0JlU5dCZVOXQmVTl0JlU5dCZVOXQmVTl0JlU5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQmVSk0JlUpNCZVKTQmVSk0JlUpNCZVKTQ - mVSk0JlUpO3Qsf/t0LH/7dCx/+3Qsf/t0LH/7dCx/+3Qsf/t0LH///bw///28P//9vD///bw///28P// - 9vD///bw///28P/64cr/+uHK//rhyv/64cr/+uHK//rhyv/64cr/+uHK//vjzP/748z/++PM//vjzP/7 - 48z/++PM//vjzP/748z/++PQ//vj0P/749D/++PQ//vj0P/749D/++PQ//vj0P/75tP/++bT//vm0//7 - 5tP/++bT//vm0//75tP/++bT//vp1f/76dX/++nV//vp1f/76dX/++nV//vp1f/76dX//OnY//zp2P/8 - 6dj//OnY//zp2P/86dj//OnY//zp2P/86tv//Orb//zq2//86tv//Orb//zq2//86tv//Orb/////f// - //3////9/////f////3////9/////f////3/0pxw/9KccP/SnHD/0pxw/9KccP/SnHD/0pxw/9KccP/u - 2cD/7tnA/+7ZwP/u2cD/7tnA/+7ZwP/u2cD/7tnA/9CZVOXQmVTl0JlU5dCZVOXQmVTl0JlU5dCZVOXQ - mVTlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAANCZVKTQmVSk0JlUpNCZVKTQmVSk0JlUpNCZVKTQmVSk7dCx/+3Qsf/t0LH/7dCx/+3Qsf/t - 0LH/7dCx/+3Qsf//9vD///bw///28P//9vD///bw///28P//9vD///bw//rhyv/64cr/+uHK//rhyv/6 - 4cr/+uHK//rhyv/64cr/++PM//vjzP/748z/++PM//vjzP/748z/++PM//vjzP/749D/++PQ//vj0P/7 - 49D/++PQ//vj0P/749D/++PQ//vm0//75tP/++bT//vm0//75tP/++bT//vm0//75tP/++nV//vp1f/7 - 6dX/++nV//vp1f/76dX/++nV//vp1f/86dj//OnY//zp2P/86dj//OnY//zp2P/86dj//OnY//zq2//8 - 6tv//Orb//zq2//86tv//Orb//zq2//86tv////9/////f////3////9/////f////3////9/////f/S - nHD/0pxw/9KccP/SnHD/0pxw/9KccP/SnHD/0pxw/+7ZwP/u2cD/7tnA/+7ZwP/u2cD/7tnA/+7ZwP/u - 2cD/0JlU5dCZVOXQmVTl0JlU5dCZVOXQmVTl0JlU5dCZVOUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JlUpNCZVKTQmVSk0JlUpNCZVKTQ - mVSk0JlUpNCZVKTt0LH/7dCx/+3Qsf/t0LH/7dCx/+3Qsf/t0LH/7dCx///28P//9vD///bw///28P// - 9vD///bw///28P//9vD/+uHK//rhyv/64cr/+uHK//rhyv/64cr/+uHK//rhyv/748z/++PM//vjzP/7 - 48z/++PM//vjzP/748z/++PM//vj0P/749D/++PQ//vj0P/749D/++PQ//vj0P/749D/++bT//vm0//7 - 5tP/++bT//vm0//75tP/++bT//vm0//76dX/++nV//vp1f/76dX/++nV//vp1f/76dX/++nV//zp2P/8 - 6dj//OnY//zp2P/86dj//OnY//zp2P/86dj//Orb//zq2//86tv//Orb//zq2//86tv//Orb//zq2/// - //3////9/////f////3////9/////f////3////9/9KccP/SnHD/0pxw/9KccP/SnHD/0pxw/9KccP/S - nHD/7tnA/+7ZwP/u2cD/7tnA/+7ZwP/u2cD/7tnA/+7ZwP/QmVTl0JlU5dCZVOXQmVTl0JlU5dCZVOXQ - mVTl0JlU5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAADQmVSk0JlUpNCZVKTQmVSk0JlUpNCZVKTQmVSk0JlUpO3Qsf/t0LH/7dCx/+3Qsf/t - 0LH/7dCx/+3Qsf/t0LH///bw///28P//9vD///bw///28P//9vD///bw///28P/64cr/+uHK//rhyv/6 - 4cr/+uHK//rhyv/64cr/+uHK//vjzP/748z/++PM//vjzP/748z/++PM//vjzP/748z/++PQ//vj0P/7 - 49D/++PQ//vj0P/749D/++PQ//vj0P/75tP/++bT//vm0//75tP/++bT//vm0//75tP/++bT//vp1f/7 - 6dX/++nV//vp1f/76dX/++nV//vp1f/76dX//OnY//zp2P/86dj//OnY//zp2P/86dj//OnY//zp2P/8 - 6tv//Orb//zq2//86tv//Orb//zq2//86tv//Orb/////f////3////9/////f////3////9/////f// - //3/0pxw/9KccP/SnHD/0pxw/9KccP/SnHD/0pxw/9KccP/u2cD/7tnA/+7ZwP/u2cD/7tnA/+7ZwP/u - 2cD/7tnA/9CZVOXQmVTl0JlU5dCZVOXQmVTl0JlU5dCZVOXQmVTlAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCZVKTQmVSk0JlUpNCZVKTQ - mVSk0JlUpNCZVKTQmVSk7dCx/+3Qsf/t0LH/7dCx/+3Qsf/t0LH/7dCx/+3Qsf//9vD///bw///28P// - 9vD///bw///28P//9vD///bw//rhyv/64cr/+uHK//rhyv/64cr/+uHK//rhyv/64cr/++PM//vjzP/7 - 48z/++PM//vjzP/748z/++PM//vjzP/749D/++PQ//vj0P/749D/++PQ//vj0P/749D/++PQ//vm0//7 - 5tP/++bT//vm0//75tP/++bT//vm0//75tP/++nV//vp1f/76dX/++nV//vp1f/76dX/++nV//vp1f/8 - 6dj//OnY//zp2P/86dj//OnY//zp2P/86dj//OnY//zq2//86tv//Orb//zq2//86tv//Orb//zq2//8 - 6tv////9/////f////3////9/////f////3////9/////f/SnHD/0pxw/9KccP/SnHD/0pxw/9KccP/S - nHD/0pxw/+7ZwP/u2cD/7tnA/+7ZwP/u2cD/7tnA/+7ZwP/u2cD/0JlU5dCZVOXQmVTl0JlU5dCZVOXQ - mVTl0JlU5dCZVOUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAA0JlUpNCZVKTQmVSk0JlUpNCZVKTQmVSk0JlUpNCZVKTt0LH/7dCx/+3Qsf/t - 0LH/7dCx/+3Qsf/t0LH/7dCx///28P//9vD///bw///28P//9vD///bw///28P//9vD/+uHK//rhyv/6 - 4cr/+uHK//rhyv/64cr/+uHK//rhyv/748z/++PM//vjzP/748z/++PM//vjzP/748z/++PM//vj0P/7 - 49D/++PQ//vj0P/749D/++PQ//vj0P/749D/++bT//vm0//75tP/++bT//vm0//75tP/++bT//vm0//7 - 6dX/++nV//vp1f/76dX/++nV//vp1f/76dX/++nV//zp2P/86dj//OnY//zp2P/86dj//OnY//zp2P/8 - 6dj//Orb//zq2//86tv//Orb//zq2//86tv//Orb//zq2/////3////9/////f////3////9/////f// - //3////9/9KccP/SnHD/0pxw/9KccP/SnHD/0pxw/9KccP/SnHD/7tnA/+7ZwP/u2cD/7tnA/+7ZwP/u - 2cD/7tnA/+7ZwP/QmVTl0JlU5dCZVOXQmVTl0JlU5dCZVOXQmVTl0JlU5QAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQmVSk0JlUpNCZVKTQ - mVSk0JlUpNCZVKTQmVSk0JlUpO3Qsf/t0LH/7dCx/+3Qsf/t0LH/7dCx/+3Qsf/t0LH///bw///28P// - 9vD///bw///28P//9vD///bw///28P/64cr/+uHK//rhyv/64cr/+uHK//rhyv/64cr/+uHK//vjzP/7 - 48z/++PM//vjzP/748z/++PM//vjzP/748z/++PQ//vj0P/749D/++PQ//vj0P/749D/++PQ//vj0P/7 - 5tP/++bT//vm0//75tP/++bT//vm0//75tP/++bT//vp1f/76dX/++nV//vp1f/76dX/++nV//vp1f/7 - 6dX//OnY//zp2P/86dj//OnY//zp2P/86dj//OnY//zp2P/86tv//Orb//zq2//86tv//Orb//zq2//8 - 6tv//Orb/////f////3////9/////f////3////9/////f////3/0pxw/9KccP/SnHD/0pxw/9KccP/S - nHD/0pxw/9KccP/u2cD/7tnA/+7ZwP/u2cD/7tnA/+7ZwP/u2cD/7tnA/9CZVOXQmVTl0JlU5dCZVOXQ - mVTl0JlU5dCZVOXQmVTlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAANWeV5LVnleS1Z5XktWeV5LVnleS1Z5XktWeV5LVnleS68qk/+vKpP/r - yqT/68qk/+vKpP/ryqT/68qk/+vKpP///fv///37///9+////fv///37///9+////fv///37//3p1f/9 - 6dX//enV//3p1f/96dX//enV//3p1f/96dX//evY//3r2P/969j//evY//3r2P/969j//evY//3r2P/9 - 6tv//erb//3q2//96tv//erb//3q2//96tv//erb//3t3//97d///e3f//3t3//97d///e3f//3t3//9 - 7d///fDi//3w4v/98OL//fDi//3w4v/98OL//fDi//3w4v/98eT//fHk//3x5P/98eT//fHk//3x5P/9 - 8eT//fHk//zw5P/88OT//PDk//zw5P/88OT//PDk//zw5P/88OT///////////////////////////// - ///////////////gn2//4J9v/+Cfb//gn2//4J9v/+Cfb//gn2//4J9v///7+f//+/n///v5///7+f// - +/n///v5///7+f//+/n/37eG/9+3hv/ft4b/37eG/9+3hv/ft4b/37eG/9+3hv8AAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1Z5XktWeV5LV - nleS1Z5XktWeV5LVnleS1Z5XktWeV5LryqT/68qk/+vKpP/ryqT/68qk/+vKpP/ryqT/68qk///9+/// - /fv///37///9+////fv///37///9+////fv//enV//3p1f/96dX//enV//3p1f/96dX//enV//3p1f/9 - 69j//evY//3r2P/969j//evY//3r2P/969j//evY//3q2//96tv//erb//3q2//96tv//erb//3q2//9 - 6tv//e3f//3t3//97d///e3f//3t3//97d///e3f//3t3//98OL//fDi//3w4v/98OL//fDi//3w4v/9 - 8OL//fDi//3x5P/98eT//fHk//3x5P/98eT//fHk//3x5P/98eT//PDk//zw5P/88OT//PDk//zw5P/8 - 8OT//PDk//zw5P///////////////////////////////////////////+Cfb//gn2//4J9v/+Cfb//g - n2//4J9v/+Cfb//gn2////v5///7+f//+/n///v5///7+f//+/n///v5///7+f/ft4b/37eG/9+3hv/f - t4b/37eG/9+3hv/ft4b/37eG/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADVnleS1Z5XktWeV5LVnleS1Z5XktWeV5LVnleS1Z5XkuvKpP/r - yqT/68qk/+vKpP/ryqT/68qk/+vKpP/ryqT///37///9+////fv///37///9+////fv///37///9+//9 - 6dX//enV//3p1f/96dX//enV//3p1f/96dX//enV//3r2P/969j//evY//3r2P/969j//evY//3r2P/9 - 69j//erb//3q2//96tv//erb//3q2//96tv//erb//3q2//97d///e3f//3t3//97d///e3f//3t3//9 - 7d///e3f//3w4v/98OL//fDi//3w4v/98OL//fDi//3w4v/98OL//fHk//3x5P/98eT//fHk//3x5P/9 - 8eT//fHk//3x5P/88OT//PDk//zw5P/88OT//PDk//zw5P/88OT//PDk//////////////////////// - ////////////////////4J9v/+Cfb//gn2//4J9v/+Cfb//gn2//4J9v/+Cfb///+/n///v5///7+f// - +/n///v5///7+f//+/n///v5/9+3hv/ft4b/37eG/9+3hv/ft4b/37eG/9+3hv/ft4b/AAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANWeV5LV - nleS1Z5XktWeV5LVnleS1Z5XktWeV5LVnleS68qk/+vKpP/ryqT/68qk/+vKpP/ryqT/68qk/+vKpP// - /fv///37///9+////fv///37///9+////fv///37//3p1f/96dX//enV//3p1f/96dX//enV//3p1f/9 - 6dX//evY//3r2P/969j//evY//3r2P/969j//evY//3r2P/96tv//erb//3q2//96tv//erb//3q2//9 - 6tv//erb//3t3//97d///e3f//3t3//97d///e3f//3t3//97d///fDi//3w4v/98OL//fDi//3w4v/9 - 8OL//fDi//3w4v/98eT//fHk//3x5P/98eT//fHk//3x5P/98eT//fHk//zw5P/88OT//PDk//zw5P/8 - 8OT//PDk//zw5P/88OT////////////////////////////////////////////gn2//4J9v/+Cfb//g - n2//4J9v/+Cfb//gn2//4J9v///7+f//+/n///v5///7+f//+/n///v5///7+f//+/n/37eG/9+3hv/f - t4b/37eG/9+3hv/ft4b/37eG/9+3hv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1Z5XktWeV5LVnleS1Z5XktWeV5LVnleS1Z5XktWeV5Lr - yqT/68qk/+vKpP/ryqT/68qk/+vKpP/ryqT/68qk///9+////fv///37///9+////fv///37///9+/// - /fv//enV//3p1f/96dX//enV//3p1f/96dX//enV//3p1f/969j//evY//3r2P/969j//evY//3r2P/9 - 69j//evY//3q2//96tv//erb//3q2//96tv//erb//3q2//96tv//e3f//3t3//97d///e3f//3t3//9 - 7d///e3f//3t3//98OL//fDi//3w4v/98OL//fDi//3w4v/98OL//fDi//3x5P/98eT//fHk//3x5P/9 - 8eT//fHk//3x5P/98eT//PDk//zw5P/88OT//PDk//zw5P/88OT//PDk//zw5P////////////////// - /////////////////////////+Cfb//gn2//4J9v/+Cfb//gn2//4J9v/+Cfb//gn2////v5///7+f// - +/n///v5///7+f//+/n///v5///7+f/ft4b/37eG/9+3hv/ft4b/37eG/9+3hv/ft4b/37eG/wAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADV - nleS1Z5XktWeV5LVnleS1Z5XktWeV5LVnleS1Z5XkuvKpP/ryqT/68qk/+vKpP/ryqT/68qk/+vKpP/r - yqT///37///9+////fv///37///9+////fv///37///9+//96dX//enV//3p1f/96dX//enV//3p1f/9 - 6dX//enV//3r2P/969j//evY//3r2P/969j//evY//3r2P/969j//erb//3q2//96tv//erb//3q2//9 - 6tv//erb//3q2//97d///e3f//3t3//97d///e3f//3t3//97d///e3f//3w4v/98OL//fDi//3w4v/9 - 8OL//fDi//3w4v/98OL//fHk//3x5P/98eT//fHk//3x5P/98eT//fHk//3x5P/88OT//PDk//zw5P/8 - 8OT//PDk//zw5P/88OT//PDk////////////////////////////////////////////4J9v/+Cfb//g - n2//4J9v/+Cfb//gn2//4J9v/+Cfb///+/n///v5///7+f//+/n///v5///7+f//+/n///v5/9+3hv/f - t4b/37eG/9+3hv/ft4b/37eG/9+3hv/ft4b/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANWeV5LVnleS1Z5XktWeV5LVnleS1Z5XktWeV5LV - nleS68qk/+vKpP/ryqT/68qk/+vKpP/ryqT/68qk/+vKpP///fv///37///9+////fv///37///9+/// - /fv///37//3p1f/96dX//enV//3p1f/96dX//enV//3p1f/96dX//evY//3r2P/969j//evY//3r2P/9 - 69j//evY//3r2P/96tv//erb//3q2//96tv//erb//3q2//96tv//erb//3t3//97d///e3f//3t3//9 - 7d///e3f//3t3//97d///fDi//3w4v/98OL//fDi//3w4v/98OL//fDi//3w4v/98eT//fHk//3x5P/9 - 8eT//fHk//3x5P/98eT//fHk//zw5P/88OT//PDk//zw5P/88OT//PDk//zw5P/88OT///////////// - ///////////////////////////////gn2//4J9v/+Cfb//gn2//4J9v/+Cfb//gn2//4J9v///7+f// - +/n///v5///7+f//+/n///v5///7+f//+/n/37eG/9+3hv/ft4b/37eG/9+3hv/ft4b/37eG/9+3hv8A - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAA1Z5XktWeV5LVnleS1Z5XktWeV5LVnleS1Z5XktWeV5LryqT/68qk/+vKpP/ryqT/68qk/+vKpP/r - yqT/68qk///9+////fv///37///9+////fv///37///9+////fv//enV//3p1f/96dX//enV//3p1f/9 - 6dX//enV//3p1f/969j//evY//3r2P/969j//evY//3r2P/969j//evY//3q2//96tv//erb//3q2//9 - 6tv//erb//3q2//96tv//e3f//3t3//97d///e3f//3t3//97d///e3f//3t3//98OL//fDi//3w4v/9 - 8OL//fDi//3w4v/98OL//fDi//3x5P/98eT//fHk//3x5P/98eT//fHk//3x5P/98eT//PDk//zw5P/8 - 8OT//PDk//zw5P/88OT//PDk//zw5P///////////////////////////////////////////+Cfb//g - n2//4J9v/+Cfb//gn2//4J9v/+Cfb//gn2////v5///7+f//+/n///v5///7+f//+/n///v5///7+f/f - t4b/37eG/9+3hv/ft4b/37eG/9+3hv/ft4b/37eG/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADao1qE2qNahNqjWoTao1qE2qNahNqjWoTa - o1qE2qNahOvFmf/rxZn/68WZ/+vFmf/rxZn/68WZ/+vFmf/rxZn///////////////////////////// - ///////////////87+L//O/i//zv4v/87+L//O/i//zv4v/87+L//O/i//3w5//98Of//fDn//3w5//9 - 8Of//fDn//3w5//98Of//fHr//3x6//98ev//fHr//3x6//98ev//fHr//3x6//99e7//fXu//317v/9 - 9e7//fXu//317v/99e7//fXu//348f/9+PH//fjx//348f/9+PH//fjx//348f/9+PH//fr3//369//9 - +vf//fr3//369//9+vf//fr3//369////Pr///z6///8+v///Pr///z6///8+v///Pr///z6//////// - /////////////////////////////////////vv3//779//++/f//vv3//779//++/f//vv3//779//0 - 2r//9Nq///Tav//02r//9Nq///Tav//02r//9Nq//9qjWurao1rq2qNa6tqjWurao1rq2qNa6tqjWura - o1rqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAANqjWoTao1qE2qNahNqjWoTao1qE2qNahNqjWoTao1qE68WZ/+vFmf/rxZn/68WZ/+vFmf/r - xZn/68WZ/+vFmf////////////////////////////////////////////zv4v/87+L//O/i//zv4v/8 - 7+L//O/i//zv4v/87+L//fDn//3w5//98Of//fDn//3w5//98Of//fDn//3w5//98ev//fHr//3x6//9 - 8ev//fHr//3x6//98ev//fHr//317v/99e7//fXu//317v/99e7//fXu//317v/99e7//fjx//348f/9 - +PH//fjx//348f/9+PH//fjx//348f/9+vf//fr3//369//9+vf//fr3//369//9+vf//fr3///8+v// - /Pr///z6///8+v///Pr///z6///8+v///Pr////////////////////////////////////////////+ - +/f//vv3//779//++/f//vv3//779//++/f//vv3//Tav//02r//9Nq///Tav//02r//9Nq///Tav//0 - 2r//2qNa6tqjWurao1rq2qNa6tqjWurao1rq2qNa6tqjWuoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2qNahNqjWoTao1qE2qNahNqjWoTa - o1qE2qNahNqjWoTrxZn/68WZ/+vFmf/rxZn/68WZ/+vFmf/rxZn/68WZ//////////////////////// - /////////////////////O/i//zv4v/87+L//O/i//zv4v/87+L//O/i//zv4v/98Of//fDn//3w5//9 - 8Of//fDn//3w5//98Of//fDn//3x6//98ev//fHr//3x6//98ev//fHr//3x6//98ev//fXu//317v/9 - 9e7//fXu//317v/99e7//fXu//317v/9+PH//fjx//348f/9+PH//fjx//348f/9+PH//fjx//369//9 - +vf//fr3//369//9+vf//fr3//369//9+vf///z6///8+v///Pr///z6///8+v///Pr///z6///8+v// - //////////////////////////////////////////779//++/f//vv3//779//++/f//vv3//779//+ - +/f/9Nq///Tav//02r//9Nq///Tav//02r//9Nq///Tav//ao1rq2qNa6tqjWurao1rq2qNa6tqjWura - o1rq2qNa6gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAADao1qE2qNahNqjWoTao1qE2qNahNqjWoTao1qE2qNahOvFmf/rxZn/68WZ/+vFmf/r - xZn/68WZ/+vFmf/rxZn////////////////////////////////////////////87+L//O/i//zv4v/8 - 7+L//O/i//zv4v/87+L//O/i//3w5//98Of//fDn//3w5//98Of//fDn//3w5//98Of//fHr//3x6//9 - 8ev//fHr//3x6//98ev//fHr//3x6//99e7//fXu//317v/99e7//fXu//317v/99e7//fXu//348f/9 - +PH//fjx//348f/9+PH//fjx//348f/9+PH//fr3//369//9+vf//fr3//369//9+vf//fr3//369/// - /Pr///z6///8+v///Pr///z6///8+v///Pr///z6//////////////////////////////////////// - /////vv3//779//++/f//vv3//779//++/f//vv3//779//02r//9Nq///Tav//02r//9Nq///Tav//0 - 2r//9Nq//9qjWurao1rq2qNa6tqjWurao1rq2qNa6tqjWurao1rqAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANqjWoTao1qE2qNahNqjWoTa - o1qE2qNahNqjWoTao1qE68WZ/+vFmf/rxZn/68WZ/+vFmf/rxZn/68WZ/+vFmf////////////////// - //////////////////////////zv4v/87+L//O/i//zv4v/87+L//O/i//zv4v/87+L//fDn//3w5//9 - 8Of//fDn//3w5//98Of//fDn//3w5//98ev//fHr//3x6//98ev//fHr//3x6//98ev//fHr//317v/9 - 9e7//fXu//317v/99e7//fXu//317v/99e7//fjx//348f/9+PH//fjx//348f/9+PH//fjx//348f/9 - +vf//fr3//369//9+vf//fr3//369//9+vf//fr3///8+v///Pr///z6///8+v///Pr///z6///8+v// - /Pr////////////////////////////////////////////++/f//vv3//779//++/f//vv3//779//+ - +/f//vv3//Tav//02r//9Nq///Tav//02r//9Nq///Tav//02r//2qNa6tqjWurao1rq2qNa6tqjWura - o1rq2qNa6tqjWuoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAA2qNahNqjWoTao1qE2qNahNqjWoTao1qE2qNahNqjWoTrxZn/68WZ/+vFmf/r - xZn/68WZ/+vFmf/rxZn/68WZ/////////////////////////////////////////////O/i//zv4v/8 - 7+L//O/i//zv4v/87+L//O/i//zv4v/98Of//fDn//3w5//98Of//fDn//3w5//98Of//fDn//3x6//9 - 8ev//fHr//3x6//98ev//fHr//3x6//98ev//fXu//317v/99e7//fXu//317v/99e7//fXu//317v/9 - +PH//fjx//348f/9+PH//fjx//348f/9+PH//fjx//369//9+vf//fr3//369//9+vf//fr3//369//9 - +vf///z6///8+v///Pr///z6///8+v///Pr///z6///8+v////////////////////////////////// - //////////779//++/f//vv3//779//++/f//vv3//779//++/f/9Nq///Tav//02r//9Nq///Tav//0 - 2r//9Nq///Tav//ao1rq2qNa6tqjWurao1rq2qNa6tqjWurao1rq2qNa6gAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADao1qE2qNahNqjWoTa - o1qE2qNahNqjWoTao1qE2qNahOvFmf/rxZn/68WZ/+vFmf/rxZn/68WZ/+vFmf/rxZn///////////// - ///////////////////////////////87+L//O/i//zv4v/87+L//O/i//zv4v/87+L//O/i//3w5//9 - 8Of//fDn//3w5//98Of//fDn//3w5//98Of//fHr//3x6//98ev//fHr//3x6//98ev//fHr//3x6//9 - 9e7//fXu//317v/99e7//fXu//317v/99e7//fXu//348f/9+PH//fjx//348f/9+PH//fjx//348f/9 - +PH//fr3//369//9+vf//fr3//369//9+vf//fr3//369////Pr///z6///8+v///Pr///z6///8+v// - /Pr///z6/////////////////////////////////////////////vv3//779//++/f//vv3//779//+ - +/f//vv3//779//02r//9Nq///Tav//02r//9Nq///Tav//02r//9Nq//9qjWurao1rq2qNa6tqjWura - o1rq2qNa6tqjWurao1rqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAANqjWoTao1qE2qNahNqjWoTao1qE2qNahNqjWoTao1qE68WZ/+vFmf/r - xZn/68WZ/+vFmf/rxZn/68WZ/+vFmf////////////////////////////////////////////zv4v/8 - 7+L//O/i//zv4v/87+L//O/i//zv4v/87+L//fDn//3w5//98Of//fDn//3w5//98Of//fDn//3w5//9 - 8ev//fHr//3x6//98ev//fHr//3x6//98ev//fHr//317v/99e7//fXu//317v/99e7//fXu//317v/9 - 9e7//fjx//348f/9+PH//fjx//348f/9+PH//fjx//348f/9+vf//fr3//369//9+vf//fr3//369//9 - +vf//fr3///8+v///Pr///z6///8+v///Pr///z6///8+v///Pr///////////////////////////// - ///////////////++/f//vv3//779//++/f//vv3//779//++/f//vv3//Tav//02r//9Nq///Tav//0 - 2r//9Nq///Tav//02r//2qNa6tqjWurao1rq2qNa6tqjWurao1rq2qNa6tqjWuoAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3qdcbd6nXG3e - p1xt3qdcbd6nXG3ep1xt3qdcbd6nXG3qv4v/6r+L/+q/i//qv4v/6r+L/+q/i//qv4v/6r+L//////// - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - /////fn0//359P/9+fT//fn0//359P/9+fT//fn0//359P/78+r/+/Pq//vz6v/78+r/+/Pq//vz6v/7 - 8+r/+/Pq//jr2f/469n/+OvZ//jr2f/469n/+OvZ//jr2f/469n/+ObT//jm0//45tP/+ObT//jm0//4 - 5tP/+ObT//jm0//138X/9d/F//Xfxf/138X/9d/F//Xfxf/138X/9d/F/+nLpf/py6X/6cul/+nLpf/p - y6X/6cul/+nLpf/py6X/3qdc7d6nXO3ep1zt3qdc7d6nXO3ep1zt3qdc7d6nXO3ep1xd3qdcXd6nXF3e - p1xd3qdcXd6nXF3ep1xd3qdcXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADep1xt3qdcbd6nXG3ep1xt3qdcbd6nXG3ep1xt3qdcbeq/i//q - v4v/6r+L/+q/i//qv4v/6r+L/+q/i//qv4v///////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////////////////////9+fT//fn0//359P/9+fT//fn0//359P/9 - +fT//fn0//vz6v/78+r/+/Pq//vz6v/78+r/+/Pq//vz6v/78+r/+OvZ//jr2f/469n/+OvZ//jr2f/4 - 69n/+OvZ//jr2f/45tP/+ObT//jm0//45tP/+ObT//jm0//45tP/+ObT//Xfxf/138X/9d/F//Xfxf/1 - 38X/9d/F//Xfxf/138X/6cul/+nLpf/py6X/6cul/+nLpf/py6X/6cul/+nLpf/ep1zt3qdc7d6nXO3e - p1zt3qdc7d6nXO3ep1zt3qdc7d6nXF3ep1xd3qdcXd6nXF3ep1xd3qdcXd6nXF3ep1xdAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6nXG3e - p1xt3qdcbd6nXG3ep1xt3qdcbd6nXG3ep1xt6r+L/+q/i//qv4v/6r+L/+q/i//qv4v/6r+L/+q/i/// - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - //////////359P/9+fT//fn0//359P/9+fT//fn0//359P/9+fT/+/Pq//vz6v/78+r/+/Pq//vz6v/7 - 8+r/+/Pq//vz6v/469n/+OvZ//jr2f/469n/+OvZ//jr2f/469n/+OvZ//jm0//45tP/+ObT//jm0//4 - 5tP/+ObT//jm0//45tP/9d/F//Xfxf/138X/9d/F//Xfxf/138X/9d/F//Xfxf/py6X/6cul/+nLpf/p - y6X/6cul/+nLpf/py6X/6cul/96nXO3ep1zt3qdc7d6nXO3ep1zt3qdc7d6nXO3ep1zt3qdcXd6nXF3e - p1xd3qdcXd6nXF3ep1xd3qdcXd6nXF0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3qdcbd6nXG3ep1xt3qdcbd6nXG3ep1xt3qdcbd6nXG3q - v4v/6r+L/+q/i//qv4v/6r+L/+q/i//qv4v/6r+L//////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////fn0//359P/9+fT//fn0//359P/9 - +fT//fn0//359P/78+r/+/Pq//vz6v/78+r/+/Pq//vz6v/78+r/+/Pq//jr2f/469n/+OvZ//jr2f/4 - 69n/+OvZ//jr2f/469n/+ObT//jm0//45tP/+ObT//jm0//45tP/+ObT//jm0//138X/9d/F//Xfxf/1 - 38X/9d/F//Xfxf/138X/9d/F/+nLpf/py6X/6cul/+nLpf/py6X/6cul/+nLpf/py6X/3qdc7d6nXO3e - p1zt3qdc7d6nXO3ep1zt3qdc7d6nXO3ep1xd3qdcXd6nXF3ep1xd3qdcXd6nXF3ep1xd3qdcXQAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADe - p1xt3qdcbd6nXG3ep1xt3qdcbd6nXG3ep1xt3qdcbeq/i//qv4v/6r+L/+q/i//qv4v/6r+L/+q/i//q - v4v///////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - ///////////////9+fT//fn0//359P/9+fT//fn0//359P/9+fT//fn0//vz6v/78+r/+/Pq//vz6v/7 - 8+r/+/Pq//vz6v/78+r/+OvZ//jr2f/469n/+OvZ//jr2f/469n/+OvZ//jr2f/45tP/+ObT//jm0//4 - 5tP/+ObT//jm0//45tP/+ObT//Xfxf/138X/9d/F//Xfxf/138X/9d/F//Xfxf/138X/6cul/+nLpf/p - y6X/6cul/+nLpf/py6X/6cul/+nLpf/ep1zt3qdc7d6nXO3ep1zt3qdc7d6nXO3ep1zt3qdc7d6nXF3e - p1xd3qdcXd6nXF3ep1xd3qdcXd6nXF3ep1xdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN6nXG3ep1xt3qdcbd6nXG3ep1xt3qdcbd6nXG3e - p1xt6r+L/+q/i//qv4v/6r+L/+q/i//qv4v/6r+L/+q/i/////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////359P/9+fT//fn0//359P/9 - +fT//fn0//359P/9+fT/+/Pq//vz6v/78+r/+/Pq//vz6v/78+r/+/Pq//vz6v/469n/+OvZ//jr2f/4 - 69n/+OvZ//jr2f/469n/+OvZ//jm0//45tP/+ObT//jm0//45tP/+ObT//jm0//45tP/9d/F//Xfxf/1 - 38X/9d/F//Xfxf/138X/9d/F//Xfxf/py6X/6cul/+nLpf/py6X/6cul/+nLpf/py6X/6cul/96nXO3e - p1zt3qdc7d6nXO3ep1zt3qdc7d6nXO3ep1zt3qdcXd6nXF3ep1xd3qdcXd6nXF3ep1xd3qdcXd6nXF0A - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAA3qdcbd6nXG3ep1xt3qdcbd6nXG3ep1xt3qdcbd6nXG3qv4v/6r+L/+q/i//qv4v/6r+L/+q/i//q - v4v/6r+L//////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - /////////////////////fn0//359P/9+fT//fn0//359P/9+fT//fn0//359P/78+r/+/Pq//vz6v/7 - 8+r/+/Pq//vz6v/78+r/+/Pq//jr2f/469n/+OvZ//jr2f/469n/+OvZ//jr2f/469n/+ObT//jm0//4 - 5tP/+ObT//jm0//45tP/+ObT//jm0//138X/9d/F//Xfxf/138X/9d/F//Xfxf/138X/9d/F/+nLpf/p - y6X/6cul/+nLpf/py6X/6cul/+nLpf/py6X/3qdc7d6nXO3ep1zt3qdc7d6nXO3ep1zt3qdc7d6nXO3e - p1xd3qdcXd6nXF3ep1xd3qdcXd6nXF3ep1xd3qdcXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADep1xt3qdcbd6nXG3ep1xt3qdcbd6nXG3e - p1xt3qdcbeq/i//qv4v/6r+L/+q/i//qv4v/6r+L/+q/i//qv4v///////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////9+fT//fn0//359P/9 - +fT//fn0//359P/9+fT//fn0//vz6v/78+r/+/Pq//vz6v/78+r/+/Pq//vz6v/78+r/+OvZ//jr2f/4 - 69n/+OvZ//jr2f/469n/+OvZ//jr2f/45tP/+ObT//jm0//45tP/+ObT//jm0//45tP/+ObT//Xfxf/1 - 38X/9d/F//Xfxf/138X/9d/F//Xfxf/138X/6cul/+nLpf/py6X/6cul/+nLpf/py6X/6cul/+nLpf/e - p1zt3qdc7d6nXO3ep1zt3qdc7d6nXO3ep1zt3qdc7d6nXF3ep1xd3qdcXd6nXF3ep1xd3qdcXd6nXF3e - p1xdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAOKrXjbiq1424qteNuKrXjbiq1424qteNuKrXjbiq1424qtexuKrXsbiq17G4qtexuKrXsbi - q17G4qtexuKrXsbqu4D/6ruA/+q7gP/qu4D/6ruA/+q7gP/qu4D/6ruA/+i2dv/otnb/6LZ2/+i2dv/o - tnb/6LZ2/+i2dv/otnb/5rFs/+axbP/msWz/5rFs/+axbP/msWz/5rFs/+axbP/kr2f/5K9n/+SvZ//k - r2f/5K9n/+SvZ//kr2f/5K9n/+KrXvDiq17w4qte8OKrXvDiq17w4qte8OKrXvDiq17w4qte4+KrXuPi - q17j4qte4+KrXuPiq17j4qte4+KrXuPiq17P4qtez+KrXs/iq17P4qtez+KrXs/iq17P4qtez+KrXszi - q17M4qtezOKrXsziq17M4qtezOKrXsziq17M4qteu+KrXrviq1674qteu+KrXrviq1674qteu+KrXrvi - q16o4qteqOKrXqjiq16o4qteqOKrXqjiq16o4qteqOKrXkviq15L4qteS+KrXkviq15L4qteS+KrXkvi - q15L4qteBeKrXgXiq14F4qteBeKrXgXiq14F4qteBeKrXgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4qteNuKrXjbiq1424qteNuKrXjbi - q1424qteNuKrXjbiq17G4qtexuKrXsbiq17G4qtexuKrXsbiq17G4qtexuq7gP/qu4D/6ruA/+q7gP/q - u4D/6ruA/+q7gP/qu4D/6LZ2/+i2dv/otnb/6LZ2/+i2dv/otnb/6LZ2/+i2dv/msWz/5rFs/+axbP/m - sWz/5rFs/+axbP/msWz/5rFs/+SvZ//kr2f/5K9n/+SvZ//kr2f/5K9n/+SvZ//kr2f/4qte8OKrXvDi - q17w4qte8OKrXvDiq17w4qte8OKrXvDiq17j4qte4+KrXuPiq17j4qte4+KrXuPiq17j4qte4+KrXs/i - q17P4qtez+KrXs/iq17P4qtez+KrXs/iq17P4qtezOKrXsziq17M4qtezOKrXsziq17M4qtezOKrXszi - q1674qteu+KrXrviq1674qteu+KrXrviq1674qteu+KrXqjiq16o4qteqOKrXqjiq16o4qteqOKrXqji - q16o4qteS+KrXkviq15L4qteS+KrXkviq15L4qteS+KrXkviq14F4qteBeKrXgXiq14F4qteBeKrXgXi - q14F4qteBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAADiq1424qteNuKrXjbiq1424qteNuKrXjbiq1424qteNuKrXsbiq17G4qtexuKrXsbi - q17G4qtexuKrXsbiq17G6ruA/+q7gP/qu4D/6ruA/+q7gP/qu4D/6ruA/+q7gP/otnb/6LZ2/+i2dv/o - tnb/6LZ2/+i2dv/otnb/6LZ2/+axbP/msWz/5rFs/+axbP/msWz/5rFs/+axbP/msWz/5K9n/+SvZ//k - r2f/5K9n/+SvZ//kr2f/5K9n/+SvZ//iq17w4qte8OKrXvDiq17w4qte8OKrXvDiq17w4qte8OKrXuPi - q17j4qte4+KrXuPiq17j4qte4+KrXuPiq17j4qtez+KrXs/iq17P4qtez+KrXs/iq17P4qtez+KrXs/i - q17M4qtezOKrXsziq17M4qtezOKrXsziq17M4qtezOKrXrviq1674qteu+KrXrviq1674qteu+KrXrvi - q1674qteqOKrXqjiq16o4qteqOKrXqjiq16o4qteqOKrXqjiq15L4qteS+KrXkviq15L4qteS+KrXkvi - q15L4qteS+KrXgXiq14F4qteBeKrXgXiq14F4qteBeKrXgXiq14FAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOKrXjbiq1424qteNuKrXjbi - q1424qteNuKrXjbiq1424qtexuKrXsbiq17G4qtexuKrXsbiq17G4qtexuKrXsbqu4D/6ruA/+q7gP/q - u4D/6ruA/+q7gP/qu4D/6ruA/+i2dv/otnb/6LZ2/+i2dv/otnb/6LZ2/+i2dv/otnb/5rFs/+axbP/m - sWz/5rFs/+axbP/msWz/5rFs/+axbP/kr2f/5K9n/+SvZ//kr2f/5K9n/+SvZ//kr2f/5K9n/+KrXvDi - q17w4qte8OKrXvDiq17w4qte8OKrXvDiq17w4qte4+KrXuPiq17j4qte4+KrXuPiq17j4qte4+KrXuPi - q17P4qtez+KrXs/iq17P4qtez+KrXs/iq17P4qtez+KrXsziq17M4qtezOKrXsziq17M4qtezOKrXszi - q17M4qteu+KrXrviq1674qteu+KrXrviq1674qteu+KrXrviq16o4qteqOKrXqjiq16o4qteqOKrXqji - q16o4qteqOKrXkviq15L4qteS+KrXkviq15L4qteS+KrXkviq15L4qteBeKrXgXiq14F4qteBeKrXgXi - q14F4qteBeKrXgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAA4qteNuKrXjbiq1424qteNuKrXjbiq1424qteNuKrXjbiq17G4qtexuKrXsbi - q17G4qtexuKrXsbiq17G4qtexuq7gP/qu4D/6ruA/+q7gP/qu4D/6ruA/+q7gP/qu4D/6LZ2/+i2dv/o - tnb/6LZ2/+i2dv/otnb/6LZ2/+i2dv/msWz/5rFs/+axbP/msWz/5rFs/+axbP/msWz/5rFs/+SvZ//k - r2f/5K9n/+SvZ//kr2f/5K9n/+SvZ//kr2f/4qte8OKrXvDiq17w4qte8OKrXvDiq17w4qte8OKrXvDi - q17j4qte4+KrXuPiq17j4qte4+KrXuPiq17j4qte4+KrXs/iq17P4qtez+KrXs/iq17P4qtez+KrXs/i - q17P4qtezOKrXsziq17M4qtezOKrXsziq17M4qtezOKrXsziq1674qteu+KrXrviq1674qteu+KrXrvi - q1674qteu+KrXqjiq16o4qteqOKrXqjiq16o4qteqOKrXqjiq16o4qteS+KrXkviq15L4qteS+KrXkvi - q15L4qteS+KrXkviq14F4qteBeKrXgXiq14F4qteBeKrXgXiq14F4qteBQAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADiq1424qteNuKrXjbi - q1424qteNuKrXjbiq1424qteNuKrXsbiq17G4qtexuKrXsbiq17G4qtexuKrXsbiq17G6ruA/+q7gP/q - u4D/6ruA/+q7gP/qu4D/6ruA/+q7gP/otnb/6LZ2/+i2dv/otnb/6LZ2/+i2dv/otnb/6LZ2/+axbP/m - sWz/5rFs/+axbP/msWz/5rFs/+axbP/msWz/5K9n/+SvZ//kr2f/5K9n/+SvZ//kr2f/5K9n/+SvZ//i - q17w4qte8OKrXvDiq17w4qte8OKrXvDiq17w4qte8OKrXuPiq17j4qte4+KrXuPiq17j4qte4+KrXuPi - q17j4qtez+KrXs/iq17P4qtez+KrXs/iq17P4qtez+KrXs/iq17M4qtezOKrXsziq17M4qtezOKrXszi - q17M4qtezOKrXrviq1674qteu+KrXrviq1674qteu+KrXrviq1674qteqOKrXqjiq16o4qteqOKrXqji - q16o4qteqOKrXqjiq15L4qteS+KrXkviq15L4qteS+KrXkviq15L4qteS+KrXgXiq14F4qteBeKrXgXi - q14F4qteBeKrXgXiq14FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAOKrXjbiq1424qteNuKrXjbiq1424qteNuKrXjbiq1424qtexuKrXsbi - q17G4qtexuKrXsbiq17G4qtexuKrXsbqu4D/6ruA/+q7gP/qu4D/6ruA/+q7gP/qu4D/6ruA/+i2dv/o - tnb/6LZ2/+i2dv/otnb/6LZ2/+i2dv/otnb/5rFs/+axbP/msWz/5rFs/+axbP/msWz/5rFs/+axbP/k - r2f/5K9n/+SvZ//kr2f/5K9n/+SvZ//kr2f/5K9n/+KrXvDiq17w4qte8OKrXvDiq17w4qte8OKrXvDi - q17w4qte4+KrXuPiq17j4qte4+KrXuPiq17j4qte4+KrXuPiq17P4qtez+KrXs/iq17P4qtez+KrXs/i - q17P4qtez+KrXsziq17M4qtezOKrXsziq17M4qtezOKrXsziq17M4qteu+KrXrviq1674qteu+KrXrvi - q1674qteu+KrXrviq16o4qteqOKrXqjiq16o4qteqOKrXqjiq16o4qteqOKrXkviq15L4qteS+KrXkvi - q15L4qteS+KrXkviq15L4qteBeKrXgXiq14F4qteBeKrXgXiq14F4qteBeKrXgUAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4qteNuKrXjbi - q1424qteNuKrXjbiq1424qteNuKrXjbiq17G4qtexuKrXsbiq17G4qtexuKrXsbiq17G4qtexuq7gP/q - u4D/6ruA/+q7gP/qu4D/6ruA/+q7gP/qu4D/6LZ2/+i2dv/otnb/6LZ2/+i2dv/otnb/6LZ2/+i2dv/m - sWz/5rFs/+axbP/msWz/5rFs/+axbP/msWz/5rFs/+SvZ//kr2f/5K9n/+SvZ//kr2f/5K9n/+SvZ//k - r2f/4qte8OKrXvDiq17w4qte8OKrXvDiq17w4qte8OKrXvDiq17j4qte4+KrXuPiq17j4qte4+KrXuPi - q17j4qte4+KrXs/iq17P4qtez+KrXs/iq17P4qtez+KrXs/iq17P4qtezOKrXsziq17M4qtezOKrXszi - q17M4qtezOKrXsziq1674qteu+KrXrviq1674qteu+KrXrviq1674qteu+KrXqjiq16o4qteqOKrXqji - q16o4qteqOKrXqjiq16o4qteS+KrXkviq15L4qteS+KrXkviq15L4qteS+KrXkviq14F4qteBeKrXgXi - q14F4qteBeKrXgXiq14F4qteBQAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAA - AAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAA - AAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8A - AAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAA - AP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAA - AAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAA - AAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8A - AAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAA - AP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAA - AAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAA - AAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//// - AAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAA - AP///wAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAP///wAAAAAAAAAA - AAAAAAD///8AAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAD///8AAAAA - AAAAAAAAAAAA////AAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAA//// - AAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAA - AAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAA - AAAAAAAA//8AAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAA////AAAA - AAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAP// - /wAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAA - AAD///8AAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAD///8AAAAAAAAA - AAAAAAAA////AAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAP//AAAA - AAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD/ - /wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAA - AAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAA - AAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAA - AAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD/ - /wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAA - AAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAA - AAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAA - AAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD/ - /wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAA - AAAA//8AAAAAAAAAAAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAA - AAAAAAAAAP//AAAAAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA//8AAAAAAAAAAAAAAAAAAP//AAAA - AAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAAKAAAAEAAAACAAAAAAQAgAAAAAAAAQAAAww4AAMMOAAAA - AAAAAAAAAI9aMBSPWjAUj1owFI9aMBSPWjCEj1owhI9aMISPWjCEj1owo49aMKOPWjCjj1owo49aMLaP - WjC2j1owto9aMLaPWjDJj1owyY9aMMmPWjDJj1ow2o9aMNqPWjDaj1ow2o9aMOuPWjDrj1ow649aMOuP - WjD6j1ow+o9aMPqPWjD6lGA4/5RgOP+UYDj/lGA4/5loQP+ZaED/mWhA/5loQP+ic07/onNO/6JzTv+i - c07/rIFe/6yBXv+sgV7/rIFe/49aMNmPWjDZj1ow2Y9aMNmPWjA0j1owNI9aMDSPWjA0AAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPWjAUj1owFI9aMBSPWjAUj1owhI9aMISPWjCEj1owhI9aMKOP - WjCjj1owo49aMKOPWjC2j1owto9aMLaPWjC2j1owyY9aMMmPWjDJj1owyY9aMNqPWjDaj1ow2o9aMNqP - WjDrj1ow649aMOuPWjDrj1ow+o9aMPqPWjD6j1ow+pRgOP+UYDj/lGA4/5RgOP+ZaED/mWhA/5loQP+Z - aED/onNO/6JzTv+ic07/onNO/6yBXv+sgV7/rIFe/6yBXv+PWjDZj1ow2Y9aMNmPWjDZj1owNI9aMDSP - WjA0j1owNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj1owFI9aMBSPWjAUj1owFI9aMISP - WjCEj1owhI9aMISPWjCjj1owo49aMKOPWjCjj1owto9aMLaPWjC2j1owto9aMMmPWjDJj1owyY9aMMmP - WjDaj1ow2o9aMNqPWjDaj1ow649aMOuPWjDrj1ow649aMPqPWjD6j1ow+o9aMPqUYDj/lGA4/5RgOP+U - YDj/mWhA/5loQP+ZaED/mWhA/6JzTv+ic07/onNO/6JzTv+sgV7/rIFe/6yBXv+sgV7/j1ow2Y9aMNmP - WjDZj1ow2Y9aMDSPWjA0j1owNI9aMDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI9aMBSP - WjAUj1owFI9aMBSPWjCEj1owhI9aMISPWjCEj1owo49aMKOPWjCjj1owo49aMLaPWjC2j1owto9aMLaP - WjDJj1owyY9aMMmPWjDJj1ow2o9aMNqPWjDaj1ow2o9aMOuPWjDrj1ow649aMOuPWjD6j1ow+o9aMPqP - WjD6lGA4/5RgOP+UYDj/lGA4/5loQP+ZaED/mWhA/5loQP+ic07/onNO/6JzTv+ic07/rIFe/6yBXv+s - gV7/rIFe/49aMNmPWjDZj1ow2Y9aMNmPWjA0j1owNI9aMDSPWjA0AAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAACTXjJok14yaJNeMmiTXjJot49s/7ePbP+3j2z/t49s/9a5ov/WuaL/1rmi/9a5ov/f - xbL/38Wy/9/Fsv/fxbL/59TC/+fUwv/n1ML/59TC/+7f0//u39P/7t/T/+7f0//16uL/9eri//Xq4v/1 - 6uL/+/Tv//v07//79O//+/Tv//369v/9+vb//fr2//369v///v3///79///+/f///v3/++vf//vr3//7 - 69//++vf//vv5v/77+b/++/m//vv5v/AnH//wJx//8Ccf//AnH//k14yb5NeMm+TXjJvk14ybwAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAk14yaJNeMmiTXjJok14yaLePbP+3j2z/t49s/7ePbP/W - uaL/1rmi/9a5ov/WuaL/38Wy/9/Fsv/fxbL/38Wy/+fUwv/n1ML/59TC/+fUwv/u39P/7t/T/+7f0//u - 39P/9eri//Xq4v/16uL/9eri//v07//79O//+/Tv//v07//9+vb//fr2//369v/9+vb///79///+/f// - /v3///79//vr3//769//++vf//vr3//77+b/++/m//vv5v/77+b/wJx//8Ccf//AnH//wJx//5NeMm+T - XjJvk14yb5NeMm8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJNeMmiTXjJok14yaJNeMmi3 - j2z/t49s/7ePbP+3j2z/1rmi/9a5ov/WuaL/1rmi/9/Fsv/fxbL/38Wy/9/Fsv/n1ML/59TC/+fUwv/n - 1ML/7t/T/+7f0//u39P/7t/T//Xq4v/16uL/9eri//Xq4v/79O//+/Tv//v07//79O///fr2//369v/9 - +vb//fr2///+/f///v3///79///+/f/769//++vf//vr3//769//++/m//vv5v/77+b/++/m/8Ccf//A - nH//wJx//8Ccf/+TXjJvk14yb5NeMm+TXjJvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACT - XjJok14yaJNeMmiTXjJot49s/7ePbP+3j2z/t49s/9a5ov/WuaL/1rmi/9a5ov/fxbL/38Wy/9/Fsv/f - xbL/59TC/+fUwv/n1ML/59TC/+7f0//u39P/7t/T/+7f0//16uL/9eri//Xq4v/16uL/+/Tv//v07//7 - 9O//+/Tv//369v/9+vb//fr2//369v///v3///79///+/f///v3/++vf//vr3//769//++vf//vv5v/7 - 7+b/++/m//vv5v/AnH//wJx//8Ccf//AnH//k14yb5NeMm+TXjJvk14ybwAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAmGM1iZhjNYmYYzWJmGM1icejhP/Ho4T/x6OE/8ejhP////////////////// - //////////////////////////////////////////////////////////////////////78///+/P// - /vz///78//779//++/f//vv3//779//+9/H//vfx//738f/+9/H//vbx//728f/+9vH//vbx/+Sthf/k - rYX/5K2F/+Sthf/66Nv/+ujb//ro2//66Nv/zq6U/86ulP/OrpT/zq6U/5hjNYuYYzWLmGM1i5hjNYsA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJhjNYmYYzWJmGM1iZhjNYnHo4T/x6OE/8ejhP/H - o4T///////////////////////////////////////////////////////////////////////////// - ///////////+/P///vz///78///+/P/++/f//vv3//779//++/f//vfx//738f/+9/H//vfx//728f/+ - 9vH//vbx//728f/krYX/5K2F/+Sthf/krYX/+ujb//ro2//66Nv/+ujb/86ulP/OrpT/zq6U/86ulP+Y - YzWLmGM1i5hjNYuYYzWLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYYzWJmGM1iZhjNYmY - YzWJx6OE/8ejhP/Ho4T/x6OE//////////////////////////////////////////////////////// - /////////////////////////////////vz///78///+/P///vz//vv3//779//++/f//vv3//738f/+ - 9/H//vfx//738f/+9vH//vbx//728f/+9vH/5K2F/+Sthf/krYX/5K2F//ro2//66Nv/+ujb//ro2//O - rpT/zq6U/86ulP/OrpT/mGM1i5hjNYuYYzWLmGM1iwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAmGM1iZhjNYmYYzWJmGM1icejhP/Ho4T/x6OE/8ejhP////////////////////////////////// - //////////////////////////////////////////////////////78///+/P///vz///78//779//+ - +/f//vv3//779//+9/H//vfx//738f/+9/H//vbx//728f/+9vH//vbx/+Sthf/krYX/5K2F/+Sthf/6 - 6Nv/+ujb//ro2//66Nv/zq6U/86ulP/OrpT/zq6U/5hjNYuYYzWLmGM1i5hjNYsAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAJ1oOFedaDhXnWg4V51oOFedaDj2nWg49p1oOPadaDj2s4RY/7OEWP+z - hFj/s4RY/9mkev/ZpHr/2aR6/9mkev/YnW7/2J1u/9idbv/YnW7/15pp/9eaaf/Xmmn/15pp/9iVYv/Y - lWL/2JVi/9iVYv/WkVz/1pFc/9aRXP/WkVz/1I5Y/9SOWP/Ujlj/1I5Y/9ONVv/TjVb/041W/9ONVv/i - nGj/4pxo/+KcaP/inGj/+uPR//rj0f/649H/+uPR/9i6of/YuqH/2Lqh/9i6of+daDienWg4np1oOJ6d - aDieAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACdaDhXnWg4V51oOFedaDhXnWg49p1oOPad - aDj2nWg49rOEWP+zhFj/s4RY/7OEWP/ZpHr/2aR6/9mkev/ZpHr/2J1u/9idbv/YnW7/2J1u/9eaaf/X - mmn/15pp/9eaaf/YlWL/2JVi/9iVYv/YlWL/1pFc/9aRXP/WkVz/1pFc/9SOWP/Ujlj/1I5Y/9SOWP/T - jVb/041W/9ONVv/TjVb/4pxo/+KcaP/inGj/4pxo//rj0f/649H/+uPR//rj0f/YuqH/2Lqh/9i6of/Y - uqH/nWg4np1oOJ6daDienWg4ngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnWg4V51oOFed - aDhXnWg4V51oOPadaDj2nWg49p1oOPazhFj/s4RY/7OEWP+zhFj/2aR6/9mkev/ZpHr/2aR6/9idbv/Y - nW7/2J1u/9idbv/Xmmn/15pp/9eaaf/Xmmn/2JVi/9iVYv/YlWL/2JVi/9aRXP/WkVz/1pFc/9aRXP/U - jlj/1I5Y/9SOWP/Ujlj/041W/9ONVv/TjVb/041W/+KcaP/inGj/4pxo/+KcaP/649H/+uPR//rj0f/6 - 49H/2Lqh/9i6of/YuqH/2Lqh/51oOJ6daDienWg4np1oOJ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAJ1oOFedaDhXnWg4V51oOFedaDj2nWg49p1oOPadaDj2s4RY/7OEWP+zhFj/s4RY/9mkev/Z - pHr/2aR6/9mkev/YnW7/2J1u/9idbv/YnW7/15pp/9eaaf/Xmmn/15pp/9iVYv/YlWL/2JVi/9iVYv/W - kVz/1pFc/9aRXP/WkVz/1I5Y/9SOWP/Ujlj/1I5Y/9ONVv/TjVb/041W/9ONVv/inGj/4pxo/+KcaP/i - nGj/+uPR//rj0f/649H/+uPR/9i6of/YuqH/2Lqh/9i6of+daDienWg4np1oOJ6daDieAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACjbjsUo247FKNuOxSjbjsUo247q6NuO6ujbjuro247q9Wti//V - rYv/1a2L/9Wti//98OX//fDl//3w5f/98OX/98eh//fHof/3x6H/98eh//fPrP/3z6z/98+s//fPrP/5 - 1bT/+dW0//nVtP/51bT/+Nq8//javP/42rz/+Nq8//jewf/43sH/+N7B//jewf/64cX/+uHF//rhxf/6 - 4cX/+uTM//rkzP/65Mz/+uTM//317P/99ez//fXs//317P/izrn/4s65/+LOuf/izrn/o247s6NuO7Oj - bjuzo247swAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo247FKNuOxSjbjsUo247FKNuO6uj - bjuro247q6NuO6vVrYv/1a2L/9Wti//VrYv//fDl//3w5f/98OX//fDl//fHof/3x6H/98eh//fHof/3 - z6z/98+s//fPrP/3z6z/+dW0//nVtP/51bT/+dW0//javP/42rz/+Nq8//javP/43sH/+N7B//jewf/4 - 3sH/+uHF//rhxf/64cX/+uHF//rkzP/65Mz/+uTM//rkzP/99ez//fXs//317P/99ez/4s65/+LOuf/i - zrn/4s65/6NuO7Ojbjuzo247s6NuO7MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKNuOxSj - bjsUo247FKNuOxSjbjuro247q6NuO6ujbjur1a2L/9Wti//VrYv/1a2L//3w5f/98OX//fDl//3w5f/3 - x6H/98eh//fHof/3x6H/98+s//fPrP/3z6z/98+s//nVtP/51bT/+dW0//nVtP/42rz/+Nq8//javP/4 - 2rz/+N7B//jewf/43sH/+N7B//rhxf/64cX/+uHF//rhxf/65Mz/+uTM//rkzP/65Mz//fXs//317P/9 - 9ez//fXs/+LOuf/izrn/4s65/+LOuf+jbjuzo247s6NuO7OjbjuzAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAACjbjsUo247FKNuOxSjbjsUo247q6NuO6ujbjuro247q9Wti//VrYv/1a2L/9Wti//9 - 8OX//fDl//3w5f/98OX/98eh//fHof/3x6H/98eh//fPrP/3z6z/98+s//fPrP/51bT/+dW0//nVtP/5 - 1bT/+Nq8//javP/42rz/+Nq8//jewf/43sH/+N7B//jewf/64cX/+uHF//rhxf/64cX/+uTM//rkzP/6 - 5Mz/+uTM//317P/99ez//fXs//317P/izrn/4s65/+LOuf/izrn/o247s6NuO7Ojbjuzo247swAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKl0PyipdD8oqXQ/KKl0Pyi2 - hVX/toVV/7aFVf+2hVX//v79//7+/f/+/v3//v79//rewf/63sH/+t7B//rewf/63L7/+ty+//rcvv/6 - 3L7/+du///nbv//527//+du///nbv//527//+du///nbv//53cD/+d3A//ndwP/53cD/+tu///rbv//6 - 27//+tu///rcwv/63ML/+tzC//rcwv/9697//eve//3r3v/9697/7NzN/+zczf/s3M3/7NzN/6l0P8qp - dD/KqXQ/yql0P8oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACp - dD8oqXQ/KKl0PyipdD8otoVV/7aFVf+2hVX/toVV//7+/f/+/v3//v79//7+/f/63sH/+t7B//rewf/6 - 3sH/+ty+//rcvv/63L7/+ty+//nbv//527//+du///nbv//527//+du///nbv//527//+d3A//ndwP/5 - 3cD/+d3A//rbv//627//+tu///rbv//63ML/+tzC//rcwv/63ML//eve//3r3v/9697//eve/+zczf/s - 3M3/7NzN/+zczf+pdD/KqXQ/yql0P8qpdD/KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAqXQ/KKl0PyipdD8oqXQ/KLaFVf+2hVX/toVV/7aFVf/+/v3//v79//7+/f/+ - /v3/+t7B//rewf/63sH/+t7B//rcvv/63L7/+ty+//rcvv/527//+du///nbv//527//+du///nbv//5 - 27//+du///ndwP/53cD/+d3A//ndwP/627//+tu///rbv//627//+tzC//rcwv/63ML/+tzC//3r3v/9 - 697//eve//3r3v/s3M3/7NzN/+zczf/s3M3/qXQ/yql0P8qpdD/KqXQ/ygAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKl0PyipdD8oqXQ/KKl0Pyi2hVX/toVV/7aFVf+2 - hVX//v79//7+/f/+/v3//v79//rewf/63sH/+t7B//rewf/63L7/+ty+//rcvv/63L7/+du///nbv//5 - 27//+du///nbv//527//+du///nbv//53cD/+d3A//ndwP/53cD/+tu///rbv//627//+tu///rcwv/6 - 3ML/+tzC//rcwv/9697//eve//3r3v/9697/7NzN/+zczf/s3M3/7NzN/6l0P8qpdD/KqXQ/yql0P8oA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwekIesHpCHrB6Qh6w - ekIeuIVR/7iFUf+4hVH/uIVR//78+f/+/Pn//vz5//78+f/53L7/+dy+//ncvv/53L7/+Nu+//jbvv/4 - 277/+Nu+//jcv//43L//+Ny///jcv//528H/+dvB//nbwf/528H/+dzA//ncwP/53MD/+dzA//ndwf/5 - 3cH/+d3B//ndwf/63cL/+t3C//rdwv/63cL/++fU//vn1P/759T/++fU//Xt4v/17eL/9e3i//Xt4v+w - ekLksHpC5LB6QuSwekLkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAsHpCHrB6Qh6wekIesHpCHriFUf+4hVH/uIVR/7iFUf/+/Pn//vz5//78+f/+/Pn/+dy+//ncvv/5 - 3L7/+dy+//jbvv/4277/+Nu+//jbvv/43L//+Ny///jcv//43L//+dvB//nbwf/528H/+dvB//ncwP/5 - 3MD/+dzA//ncwP/53cH/+d3B//ndwf/53cH/+t3C//rdwv/63cL/+t3C//vn1P/759T/++fU//vn1P/1 - 7eL/9e3i//Xt4v/17eL/sHpC5LB6QuSwekLksHpC5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAALB6Qh6wekIesHpCHrB6Qh64hVH/uIVR/7iFUf+4hVH//vz5//78+f/+ - /Pn//vz5//ncvv/53L7/+dy+//ncvv/4277/+Nu+//jbvv/4277/+Ny///jcv//43L//+Ny///nbwf/5 - 28H/+dvB//nbwf/53MD/+dzA//ncwP/53MD/+d3B//ndwf/53cH/+d3B//rdwv/63cL/+t3C//rdwv/7 - 59T/++fU//vn1P/759T/9e3i//Xt4v/17eL/9e3i/7B6QuSwekLksHpC5LB6QuQAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwekIesHpCHrB6Qh6wekIeuIVR/7iFUf+4 - hVH/uIVR//78+f/+/Pn//vz5//78+f/53L7/+dy+//ncvv/53L7/+Nu+//jbvv/4277/+Nu+//jcv//4 - 3L//+Ny///jcv//528H/+dvB//nbwf/528H/+dzA//ncwP/53MD/+dzA//ndwf/53cH/+d3B//ndwf/6 - 3cL/+t3C//rdwv/63cL/++fU//vn1P/759T/++fU//Xt4v/17eL/9e3i//Xt4v+wekLksHpC5LB6QuSw - ekLkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtoFGCbaBRgm2 - gUYJtoFGCbiESv+4hEr/uIRK/7iESv/++/f//vv3//779//++/f/+dzA//ncwP/53MD/+dzA//jcvv/4 - 3L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Nu///jbv//427//+Nu///ndv//53b//+d2///ndv//5 - 3b//+d2///ndv//53b//+d3C//ndwv/53cL/+d3C//viy//74sv/++LL//viy//8+fX//Pn1//z59f/8 - +fX/toFG+7aBRvu2gUb7toFG+7aBRgG2gUYBtoFGAbaBRgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAALaBRgm2gUYJtoFGCbaBRgm4hEr/uIRK/7iESv+4hEr//vv3//779//++/f//vv3//ncwP/5 - 3MD/+dzA//ncwP/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jbv//427//+Nu///jbv//5 - 3b//+d2///ndv//53b//+d2///ndv//53b//+d2///ndwv/53cL/+d3C//ndwv/74sv/++LL//viy//7 - 4sv//Pn1//z59f/8+fX//Pn1/7aBRvu2gUb7toFG+7aBRvu2gUYBtoFGAbaBRgG2gUYBAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC2gUYJtoFGCbaBRgm2gUYJuIRK/7iESv+4hEr/uIRK//779//+ - +/f//vv3//779//53MD/+dzA//ncwP/53MD/+Ny+//jcvv/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/4 - 27//+Nu///jbv//427//+d2///ndv//53b//+d2///ndv//53b//+d2///ndv//53cL/+d3C//ndwv/5 - 3cL/++LL//viy//74sv/++LL//z59f/8+fX//Pn1//z59f+2gUb7toFG+7aBRvu2gUb7toFGAbaBRgG2 - gUYBtoFGAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtoFGCbaBRgm2gUYJtoFGCbiESv+4 - hEr/uIRK/7iESv/++/f//vv3//779//++/f/+dzA//ncwP/53MD/+dzA//jcvv/43L7/+Ny+//jcvv/4 - 3L7/+Ny+//jcvv/43L7/+Nu///jbv//427//+Nu///ndv//53b//+d2///ndv//53b//+d2///ndv//5 - 3b//+d3C//ndwv/53cL/+d3C//viy//74sv/++LL//viy//8+fX//Pn1//z59f/8+fX/toFG+7aBRvu2 - gUb7toFG+7aBRgG2gUYBtoFGAbaBRgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAC8h0r5vIdK+byHSvm8h0r5/Pbw//z28P/89vD//Pbw//nfx//538f/+d/H//nfx//5 - 3Lz/+dy8//ncvP/53Lz/+ty+//rcvv/63L7/+ty+//rbwP/628D/+tvA//rbwP/63cL/+t3C//rdwv/6 - 3cL/+t3B//rdwf/63cH/+t3B//ndw//53cP/+d3D//ndw//74Mn/++DJ//vgyf/74Mn///z6///8+v// - /Pr///z6/8CMUv/AjFL/wIxS/8CMUv+8h0oPvIdKD7yHSg+8h0oPAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvIdK+byHSvm8h0r5vIdK+fz28P/89vD//Pbw//z28P/5 - 38f/+d/H//nfx//538f/+dy8//ncvP/53Lz/+dy8//rcvv/63L7/+ty+//rcvv/628D/+tvA//rbwP/6 - 28D/+t3C//rdwv/63cL/+t3C//rdwf/63cH/+t3B//rdwf/53cP/+d3D//ndw//53cP/++DJ//vgyf/7 - 4Mn/++DJ///8+v///Pr///z6///8+v/AjFL/wIxS/8CMUv/AjFL/vIdKD7yHSg+8h0oPvIdKDwAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALyHSvm8h0r5vIdK+byHSvn8 - 9vD//Pbw//z28P/89vD/+d/H//nfx//538f/+d/H//ncvP/53Lz/+dy8//ncvP/63L7/+ty+//rcvv/6 - 3L7/+tvA//rbwP/628D/+tvA//rdwv/63cL/+t3C//rdwv/63cH/+t3B//rdwf/63cH/+d3D//ndw//5 - 3cP/+d3D//vgyf/74Mn/++DJ//vgyf///Pr///z6///8+v///Pr/wIxS/8CMUv/AjFL/wIxS/7yHSg+8 - h0oPvIdKD7yHSg8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 - h0r5vIdK+byHSvm8h0r5/Pbw//z28P/89vD//Pbw//nfx//538f/+d/H//nfx//53Lz/+dy8//ncvP/5 - 3Lz/+ty+//rcvv/63L7/+ty+//rbwP/628D/+tvA//rbwP/63cL/+t3C//rdwv/63cL/+t3B//rdwf/6 - 3cH/+t3B//ndw//53cP/+d3D//ndw//74Mn/++DJ//vgyf/74Mn///z6///8+v///Pr///z6/8CMUv/A - jFL/wIxS/8CMUv+8h0oPvIdKD7yHSg+8h0oPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAw41N2sONTdrDjU3aw41N2vXn2P/159j/9efY//Xn2P/65dL/+uXS//rl0v/6 - 5dL/+dq7//nau//52rv/+dq7//nbu//527v/+du7//nbu//6277/+tu+//rbvv/6277/+t3A//rdwP/6 - 3cD/+t3A//rdwP/63cD/+t3A//rdwP/53cP/+d3D//ndw//53cP/++HI//vhyP/74cj/++HI///9+/// - /fv///37///9+//Ik1b/yJNW/8iTVv/Ik1b/w41NEsONTRLDjU0Sw41NEgAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMONTdrDjU3aw41N2sONTdr159j/9efY//Xn2P/1 - 59j/+uXS//rl0v/65dL/+uXS//nau//52rv/+dq7//nau//527v/+du7//nbu//527v/+tu+//rbvv/6 - 277/+tu+//rdwP/63cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+d3D//ndw//53cP/+d3D//vhyP/7 - 4cj/++HI//vhyP///fv///37///9+////fv/yJNW/8iTVv/Ik1b/yJNW/8ONTRLDjU0Sw41NEsONTRIA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDjU3aw41N2sONTdrD - jU3a9efY//Xn2P/159j/9efY//rl0v/65dL/+uXS//rl0v/52rv/+dq7//nau//52rv/+du7//nbu//5 - 27v/+du7//rbvv/6277/+tu+//rbvv/63cD/+t3A//rdwP/63cD/+t3A//rdwP/63cD/+t3A//ndw//5 - 3cP/+d3D//ndw//74cj/++HI//vhyP/74cj///37///9+////fv///37/8iTVv/Ik1b/yJNW/8iTVv/D - jU0Sw41NEsONTRLDjU0SAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAw41N2sONTdrDjU3aw41N2vXn2P/159j/9efY//Xn2P/65dL/+uXS//rl0v/65dL/+dq7//nau//5 - 2rv/+dq7//nbu//527v/+du7//nbu//6277/+tu+//rbvv/6277/+t3A//rdwP/63cD/+t3A//rdwP/6 - 3cD/+t3A//rdwP/53cP/+d3D//ndw//53cP/++HI//vhyP/74cj/++HI///9+////fv///37///9+//I - k1b/yJNW/8iTVv/Ik1b/w41NEsONTRLDjU0Sw41NEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAMqTUbvKk1G7ypNRu8qTUbvw2cD/8NnA//DZwP/w2cD/++3h//vt4f/7 - 7eH/++3h//nav//52r//+dq///nav//53MH/+dzB//ncwf/53MH/+d7E//nexP/53sT/+d7E//rgx//6 - 4Mf/+uDH//rgx//64sr/+uLK//riyv/64sr/+uLN//rizf/64s3/+uLN//rl0P/65dD/+uXQ//rl0P// - /v3///79///+/f///v3/y45Z/8uOWf/Ljln/y45Z/8qTUfHKk1HxypNR8cqTUfHKk1FFypNRRcqTUUXK - k1FFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADKk1G7ypNRu8qTUbvKk1G78NnA//DZwP/w - 2cD/8NnA//vt4f/77eH/++3h//vt4f/52r//+dq///nav//52r//+dzB//ncwf/53MH/+dzB//nexP/5 - 3sT/+d7E//nexP/64Mf/+uDH//rgx//64Mf/+uLK//riyv/64sr/+uLK//rizf/64s3/+uLN//rizf/6 - 5dD/+uXQ//rl0P/65dD///79///+/f///v3///79/8uOWf/Ljln/y45Z/8uOWf/Kk1HxypNR8cqTUfHK - k1HxypNRRcqTUUXKk1FFypNRRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAypNRu8qTUbvK - k1G7ypNRu/DZwP/w2cD/8NnA//DZwP/77eH/++3h//vt4f/77eH/+dq///nav//52r//+dq///ncwf/5 - 3MH/+dzB//ncwf/53sT/+d7E//nexP/53sT/+uDH//rgx//64Mf/+uDH//riyv/64sr/+uLK//riyv/6 - 4s3/+uLN//rizf/64s3/+uXQ//rl0P/65dD/+uXQ///+/f///v3///79///+/f/Ljln/y45Z/8uOWf/L - jln/ypNR8cqTUfHKk1HxypNR8cqTUUXKk1FFypNRRcqTUUUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAMqTUbvKk1G7ypNRu8qTUbvw2cD/8NnA//DZwP/w2cD/++3h//vt4f/77eH/++3h//nav//5 - 2r//+dq///nav//53MH/+dzB//ncwf/53MH/+d7E//nexP/53sT/+d7E//rgx//64Mf/+uDH//rgx//6 - 4sr/+uLK//riyv/64sr/+uLN//rizf/64s3/+uLN//rl0P/65dD/+uXQ//rl0P///v3///79///+/f// - /v3/y45Z/8uOWf/Ljln/y45Z/8qTUfHKk1HxypNR8cqTUfHKk1FFypNRRcqTUUXKk1FFAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQmVSk0JlUpNCZVKTQmVSk7dCx/+3Qsf/t0LH/7dCx///28P// - 9vD///bw///28P/64cr/+uHK//rhyv/64cr/++PM//vjzP/748z/++PM//vj0P/749D/++PQ//vj0P/7 - 5tP/++bT//vm0//75tP/++nV//vp1f/76dX/++nV//zp2P/86dj//OnY//zp2P/86tv//Orb//zq2//8 - 6tv////9/////f////3////9/9KccP/SnHD/0pxw/9KccP/u2cD/7tnA/+7ZwP/u2cD/0JlU5dCZVOXQ - mVTl0JlU5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0JlUpNCZVKTQmVSk0JlUpO3Qsf/t - 0LH/7dCx/+3Qsf//9vD///bw///28P//9vD/+uHK//rhyv/64cr/+uHK//vjzP/748z/++PM//vjzP/7 - 49D/++PQ//vj0P/749D/++bT//vm0//75tP/++bT//vp1f/76dX/++nV//vp1f/86dj//OnY//zp2P/8 - 6dj//Orb//zq2//86tv//Orb/////f////3////9/////f/SnHD/0pxw/9KccP/SnHD/7tnA/+7ZwP/u - 2cD/7tnA/9CZVOXQmVTl0JlU5dCZVOUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCZVKTQ - mVSk0JlUpNCZVKTt0LH/7dCx/+3Qsf/t0LH///bw///28P//9vD///bw//rhyv/64cr/+uHK//rhyv/7 - 48z/++PM//vjzP/748z/++PQ//vj0P/749D/++PQ//vm0//75tP/++bT//vm0//76dX/++nV//vp1f/7 - 6dX//OnY//zp2P/86dj//OnY//zq2//86tv//Orb//zq2/////3////9/////f////3/0pxw/9KccP/S - nHD/0pxw/+7ZwP/u2cD/7tnA/+7ZwP/QmVTl0JlU5dCZVOXQmVTlAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAADQmVSk0JlUpNCZVKTQmVSk7dCx/+3Qsf/t0LH/7dCx///28P//9vD///bw///28P/6 - 4cr/+uHK//rhyv/64cr/++PM//vjzP/748z/++PM//vj0P/749D/++PQ//vj0P/75tP/++bT//vm0//7 - 5tP/++nV//vp1f/76dX/++nV//zp2P/86dj//OnY//zp2P/86tv//Orb//zq2//86tv////9/////f// - //3////9/9KccP/SnHD/0pxw/9KccP/u2cD/7tnA/+7ZwP/u2cD/0JlU5dCZVOXQmVTl0JlU5QAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1Z5XktWeV5LVnleS1Z5XkuvKpP/ryqT/68qk/+vKpP// - /fv///37///9+////fv//enV//3p1f/96dX//enV//3r2P/969j//evY//3r2P/96tv//erb//3q2//9 - 6tv//e3f//3t3//97d///e3f//3w4v/98OL//fDi//3w4v/98eT//fHk//3x5P/98eT//PDk//zw5P/8 - 8OT//PDk///////////////////////gn2//4J9v/+Cfb//gn2////v5///7+f//+/n///v5/9+3hv/f - t4b/37eG/9+3hv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANWeV5LVnleS1Z5XktWeV5Lr - yqT/68qk/+vKpP/ryqT///37///9+////fv///37//3p1f/96dX//enV//3p1f/969j//evY//3r2P/9 - 69j//erb//3q2//96tv//erb//3t3//97d///e3f//3t3//98OL//fDi//3w4v/98OL//fHk//3x5P/9 - 8eT//fHk//zw5P/88OT//PDk//zw5P//////////////////////4J9v/+Cfb//gn2//4J9v///7+f// - +/n///v5///7+f/ft4b/37eG/9+3hv/ft4b/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADV - nleS1Z5XktWeV5LVnleS68qk/+vKpP/ryqT/68qk///9+////fv///37///9+//96dX//enV//3p1f/9 - 6dX//evY//3r2P/969j//evY//3q2//96tv//erb//3q2//97d///e3f//3t3//97d///fDi//3w4v/9 - 8OL//fDi//3x5P/98eT//fHk//3x5P/88OT//PDk//zw5P/88OT//////////////////////+Cfb//g - n2//4J9v/+Cfb///+/n///v5///7+f//+/n/37eG/9+3hv/ft4b/37eG/wAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAA1Z5XktWeV5LVnleS1Z5XkuvKpP/ryqT/68qk/+vKpP///fv///37///9+/// - /fv//enV//3p1f/96dX//enV//3r2P/969j//evY//3r2P/96tv//erb//3q2//96tv//e3f//3t3//9 - 7d///e3f//3w4v/98OL//fDi//3w4v/98eT//fHk//3x5P/98eT//PDk//zw5P/88OT//PDk//////// - ///////////////gn2//4J9v/+Cfb//gn2////v5///7+f//+/n///v5/9+3hv/ft4b/37eG/9+3hv8A - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANqjWoTao1qE2qNahNqjWoTrxZn/68WZ/+vFmf/r - xZn///////////////////////zv4v/87+L//O/i//zv4v/98Of//fDn//3w5//98Of//fHr//3x6//9 - 8ev//fHr//317v/99e7//fXu//317v/9+PH//fjx//348f/9+PH//fr3//369//9+vf//fr3///8+v// - /Pr///z6///8+v///////////////////////vv3//779//++/f//vv3//Tav//02r//9Nq///Tav//a - o1rq2qNa6tqjWurao1rqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADao1qE2qNahNqjWoTa - o1qE68WZ/+vFmf/rxZn/68WZ///////////////////////87+L//O/i//zv4v/87+L//fDn//3w5//9 - 8Of//fDn//3x6//98ev//fHr//3x6//99e7//fXu//317v/99e7//fjx//348f/9+PH//fjx//369//9 - +vf//fr3//369////Pr///z6///8+v///Pr///////////////////////779//++/f//vv3//779//0 - 2r//9Nq///Tav//02r//2qNa6tqjWurao1rq2qNa6gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAA2qNahNqjWoTao1qE2qNahOvFmf/rxZn/68WZ/+vFmf///////////////////////O/i//zv4v/8 - 7+L//O/i//3w5//98Of//fDn//3w5//98ev//fHr//3x6//98ev//fXu//317v/99e7//fXu//348f/9 - +PH//fjx//348f/9+vf//fr3//369//9+vf///z6///8+v///Pr///z6///////////////////////+ - +/f//vv3//779//++/f/9Nq///Tav//02r//9Nq//9qjWurao1rq2qNa6tqjWuoAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAANqjWoTao1qE2qNahNqjWoTrxZn/68WZ/+vFmf/rxZn///////////// - //////////zv4v/87+L//O/i//zv4v/98Of//fDn//3w5//98Of//fHr//3x6//98ev//fHr//317v/9 - 9e7//fXu//317v/9+PH//fjx//348f/9+PH//fr3//369//9+vf//fr3///8+v///Pr///z6///8+v// - /////////////////////vv3//779//++/f//vv3//Tav//02r//9Nq///Tav//ao1rq2qNa6tqjWura - o1rqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADep1xt3qdcbd6nXG3ep1xt6r+L/+q/i//q - v4v/6r+L//////////////////////////////////////////////////////////////////////// - ///////////////9+fT//fn0//359P/9+fT/+/Pq//vz6v/78+r/+/Pq//jr2f/469n/+OvZ//jr2f/4 - 5tP/+ObT//jm0//45tP/9d/F//Xfxf/138X/9d/F/+nLpf/py6X/6cul/+nLpf/ep1zt3qdc7d6nXO3e - p1zt3qdcXd6nXF3ep1xd3qdcXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3qdcbd6nXG3e - p1xt3qdcbeq/i//qv4v/6r+L/+q/i/////////////////////////////////////////////////// - /////////////////////////////////////fn0//359P/9+fT//fn0//vz6v/78+r/+/Pq//vz6v/4 - 69n/+OvZ//jr2f/469n/+ObT//jm0//45tP/+ObT//Xfxf/138X/9d/F//Xfxf/py6X/6cul/+nLpf/p - y6X/3qdc7d6nXO3ep1zt3qdc7d6nXF3ep1xd3qdcXd6nXF0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAN6nXG3ep1xt3qdcbd6nXG3qv4v/6r+L/+q/i//qv4v///////////////////////////// - //////////////////////////////////////////////////////////359P/9+fT//fn0//359P/7 - 8+r/+/Pq//vz6v/78+r/+OvZ//jr2f/469n/+OvZ//jm0//45tP/+ObT//jm0//138X/9d/F//Xfxf/1 - 38X/6cul/+nLpf/py6X/6cul/96nXO3ep1zt3qdc7d6nXO3ep1xd3qdcXd6nXF3ep1xdAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADep1xt3qdcbd6nXG3ep1xt6r+L/+q/i//qv4v/6r+L//////// - ///////////////////////////////////////////////////////////////////////////////9 - +fT//fn0//359P/9+fT/+/Pq//vz6v/78+r/+/Pq//jr2f/469n/+OvZ//jr2f/45tP/+ObT//jm0//4 - 5tP/9d/F//Xfxf/138X/9d/F/+nLpf/py6X/6cul/+nLpf/ep1zt3qdc7d6nXO3ep1zt3qdcXd6nXF3e - p1xd3qdcXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4qteNuKrXjbiq1424qteNuKrXsbi - q17G4qtexuKrXsbqu4D/6ruA/+q7gP/qu4D/6LZ2/+i2dv/otnb/6LZ2/+axbP/msWz/5rFs/+axbP/k - r2f/5K9n/+SvZ//kr2f/4qte8OKrXvDiq17w4qte8OKrXuPiq17j4qte4+KrXuPiq17P4qtez+KrXs/i - q17P4qtezOKrXsziq17M4qtezOKrXrviq1674qteu+KrXrviq16o4qteqOKrXqjiq16o4qteS+KrXkvi - q15L4qteS+KrXgXiq14F4qteBeKrXgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOKrXjbi - q1424qteNuKrXjbiq17G4qtexuKrXsbiq17G6ruA/+q7gP/qu4D/6ruA/+i2dv/otnb/6LZ2/+i2dv/m - sWz/5rFs/+axbP/msWz/5K9n/+SvZ//kr2f/5K9n/+KrXvDiq17w4qte8OKrXvDiq17j4qte4+KrXuPi - q17j4qtez+KrXs/iq17P4qtez+KrXsziq17M4qtezOKrXsziq1674qteu+KrXrviq1674qteqOKrXqji - q16o4qteqOKrXkviq15L4qteS+KrXkviq14F4qteBeKrXgXiq14FAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAADiq1424qteNuKrXjbiq1424qtexuKrXsbiq17G4qtexuq7gP/qu4D/6ruA/+q7gP/o - tnb/6LZ2/+i2dv/otnb/5rFs/+axbP/msWz/5rFs/+SvZ//kr2f/5K9n/+SvZ//iq17w4qte8OKrXvDi - q17w4qte4+KrXuPiq17j4qte4+KrXs/iq17P4qtez+KrXs/iq17M4qtezOKrXsziq17M4qteu+KrXrvi - q1674qteu+KrXqjiq16o4qteqOKrXqjiq15L4qteS+KrXkviq15L4qteBeKrXgXiq14F4qteBQAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4qteNuKrXjbiq1424qteNuKrXsbiq17G4qtexuKrXsbq - u4D/6ruA/+q7gP/qu4D/6LZ2/+i2dv/otnb/6LZ2/+axbP/msWz/5rFs/+axbP/kr2f/5K9n/+SvZ//k - r2f/4qte8OKrXvDiq17w4qte8OKrXuPiq17j4qte4+KrXuPiq17P4qtez+KrXs/iq17P4qtezOKrXszi - q17M4qtezOKrXrviq1674qteu+KrXrviq16o4qteqOKrXqjiq16o4qteS+KrXkviq15L4qteS+KrXgXi - q14F4qteBeKrXgUAAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8A - AAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAA - AAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/8AAAAAAAAP/w - AAAAAAAA//AAAAAAAAD/8AAAAAAAAP/wAAAAAAAA//AAAAAAAAD/8AAAAAAAAP/wAAAAAAAA//AAAAAA - AAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP/wAAAAAAAA//AAAAAAAAD/8AAAAAAAAP/wAAAAAAAA// - AAAAAAAAD/8AAAAAAAAP/wAAAAAAAA//AAAAAAAAD/8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAA - AAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/ - AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAA - AAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAACgAAAAwAAAAYAAAAAEAIAAA - AAAAACQAAMMOAADDDgAAAAAAAAAAAACPWjAUj1owFI9aMBSPWjCEj1owhI9aMISPWjCjj1owo49aMKOP - WjC2j1owto9aMLaPWjDJj1owyY9aMMmPWjDaj1ow2o9aMNqPWjDrj1ow649aMOuPWjD6j1ow+o9aMPqU - YDj/lGA4/5RgOP+ZaED/mWhA/5loQP+ic07/onNO/6JzTv+sgV7/rIFe/6yBXv+PWjDZj1ow2Y9aMNmP - WjA0j1owNI9aMDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPWjAUj1owFI9aMBSPWjCEj1owhI9aMISP - WjCjj1owo49aMKOPWjC2j1owto9aMLaPWjDJj1owyY9aMMmPWjDaj1ow2o9aMNqPWjDrj1ow649aMOuP - WjD6j1ow+o9aMPqUYDj/lGA4/5RgOP+ZaED/mWhA/5loQP+ic07/onNO/6JzTv+sgV7/rIFe/6yBXv+P - WjDZj1ow2Y9aMNmPWjA0j1owNI9aMDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPWjAUj1owFI9aMBSP - WjCEj1owhI9aMISPWjCjj1owo49aMKOPWjC2j1owto9aMLaPWjDJj1owyY9aMMmPWjDaj1ow2o9aMNqP - WjDrj1ow649aMOuPWjD6j1ow+o9aMPqUYDj/lGA4/5RgOP+ZaED/mWhA/5loQP+ic07/onNO/6JzTv+s - gV7/rIFe/6yBXv+PWjDZj1ow2Y9aMNmPWjA0j1owNI9aMDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACT - XjJok14yaJNeMmi3j2z/t49s/7ePbP/WuaL/1rmi/9a5ov/fxbL/38Wy/9/Fsv/n1ML/59TC/+fUwv/u - 39P/7t/T/+7f0//16uL/9eri//Xq4v/79O//+/Tv//v07//9+vb//fr2//369v///v3///79///+/f/7 - 69//++vf//vr3//77+b/++/m//vv5v/AnH//wJx//8Ccf/+TXjJvk14yb5NeMm8AAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAACTXjJok14yaJNeMmi3j2z/t49s/7ePbP/WuaL/1rmi/9a5ov/fxbL/38Wy/9/Fsv/n - 1ML/59TC/+fUwv/u39P/7t/T/+7f0//16uL/9eri//Xq4v/79O//+/Tv//v07//9+vb//fr2//369v// - /v3///79///+/f/769//++vf//vr3//77+b/++/m//vv5v/AnH//wJx//8Ccf/+TXjJvk14yb5NeMm8A - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACTXjJok14yaJNeMmi3j2z/t49s/7ePbP/WuaL/1rmi/9a5ov/f - xbL/38Wy/9/Fsv/n1ML/59TC/+fUwv/u39P/7t/T/+7f0//16uL/9eri//Xq4v/79O//+/Tv//v07//9 - +vb//fr2//369v///v3///79///+/f/769//++vf//vr3//77+b/++/m//vv5v/AnH//wJx//8Ccf/+T - XjJvk14yb5NeMm8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYYzWJmGM1iZhjNYnHo4T/x6OE/8ejhP// - /////////////////////////////////////////////////////////////////vz///78///+/P/+ - +/f//vv3//779//+9/H//vfx//738f/+9vH//vbx//728f/krYX/5K2F/+Sthf/66Nv/+ujb//ro2//O - rpT/zq6U/86ulP+YYzWLmGM1i5hjNYsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYYzWJmGM1iZhjNYnH - o4T/x6OE/8ejhP////////////////////////////////////////////////////////////////// - /vz///78///+/P/++/f//vv3//779//+9/H//vfx//738f/+9vH//vbx//728f/krYX/5K2F/+Sthf/6 - 6Nv/+ujb//ro2//OrpT/zq6U/86ulP+YYzWLmGM1i5hjNYsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACY - YzWJmGM1iZhjNYnHo4T/x6OE/8ejhP////////////////////////////////////////////////// - /////////////////vz///78///+/P/++/f//vv3//779//+9/H//vfx//738f/+9vH//vbx//728f/k - rYX/5K2F/+Sthf/66Nv/+ujb//ro2//OrpT/zq6U/86ulP+YYzWLmGM1i5hjNYsAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAACdaDhXnWg4V51oOFedaDj2nWg49p1oOPazhFj/s4RY/7OEWP/ZpHr/2aR6/9mkev/Y - nW7/2J1u/9idbv/Xmmn/15pp/9eaaf/YlWL/2JVi/9iVYv/WkVz/1pFc/9aRXP/Ujlj/1I5Y/9SOWP/T - jVb/041W/9ONVv/inGj/4pxo/+KcaP/649H/+uPR//rj0f/YuqH/2Lqh/9i6of+daDienWg4np1oOJ4A - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACdaDhXnWg4V51oOFedaDj2nWg49p1oOPazhFj/s4RY/7OEWP/Z - pHr/2aR6/9mkev/YnW7/2J1u/9idbv/Xmmn/15pp/9eaaf/YlWL/2JVi/9iVYv/WkVz/1pFc/9aRXP/U - jlj/1I5Y/9SOWP/TjVb/041W/9ONVv/inGj/4pxo/+KcaP/649H/+uPR//rj0f/YuqH/2Lqh/9i6of+d - aDienWg4np1oOJ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACdaDhXnWg4V51oOFedaDj2nWg49p1oOPaz - hFj/s4RY/7OEWP/ZpHr/2aR6/9mkev/YnW7/2J1u/9idbv/Xmmn/15pp/9eaaf/YlWL/2JVi/9iVYv/W - kVz/1pFc/9aRXP/Ujlj/1I5Y/9SOWP/TjVb/041W/9ONVv/inGj/4pxo/+KcaP/649H/+uPR//rj0f/Y - uqH/2Lqh/9i6of+daDienWg4np1oOJ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACjbjsUo247FKNuOxSj - bjuro247q6NuO6vVrYv/1a2L/9Wti//98OX//fDl//3w5f/3x6H/98eh//fHof/3z6z/98+s//fPrP/5 - 1bT/+dW0//nVtP/42rz/+Nq8//javP/43sH/+N7B//jewf/64cX/+uHF//rhxf/65Mz/+uTM//rkzP/9 - 9ez//fXs//317P/izrn/4s65/+LOuf+jbjuzo247s6NuO7MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACj - bjsUo247FKNuOxSjbjuro247q6NuO6vVrYv/1a2L/9Wti//98OX//fDl//3w5f/3x6H/98eh//fHof/3 - z6z/98+s//fPrP/51bT/+dW0//nVtP/42rz/+Nq8//javP/43sH/+N7B//jewf/64cX/+uHF//rhxf/6 - 5Mz/+uTM//rkzP/99ez//fXs//317P/izrn/4s65/+LOuf+jbjuzo247s6NuO7MAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAACjbjsUo247FKNuOxSjbjuro247q6NuO6vVrYv/1a2L/9Wti//98OX//fDl//3w5f/3 - x6H/98eh//fHof/3z6z/98+s//fPrP/51bT/+dW0//nVtP/42rz/+Nq8//javP/43sH/+N7B//jewf/6 - 4cX/+uHF//rhxf/65Mz/+uTM//rkzP/99ez//fXs//317P/izrn/4s65/+LOuf+jbjuzo247s6NuO7MA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACpdD8oqXQ/KKl0Pyi2hVX/toVV/7aFVf/+ - /v3//v79//7+/f/63sH/+t7B//rewf/63L7/+ty+//rcvv/527//+du///nbv//527//+du///nbv//5 - 3cD/+d3A//ndwP/627//+tu///rbv//63ML/+tzC//rcwv/9697//eve//3r3v/s3M3/7NzN/+zczf+p - dD/KqXQ/yql0P8oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACpdD8oqXQ/KKl0Pyi2 - hVX/toVV/7aFVf/+/v3//v79//7+/f/63sH/+t7B//rewf/63L7/+ty+//rcvv/527//+du///nbv//5 - 27//+du///nbv//53cD/+d3A//ndwP/627//+tu///rbv//63ML/+tzC//rcwv/9697//eve//3r3v/s - 3M3/7NzN/+zczf+pdD/KqXQ/yql0P8oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACp - dD8oqXQ/KKl0Pyi2hVX/toVV/7aFVf/+/v3//v79//7+/f/63sH/+t7B//rewf/63L7/+ty+//rcvv/5 - 27//+du///nbv//527//+du///nbv//53cD/+d3A//ndwP/627//+tu///rbv//63ML/+tzC//rcwv/9 - 697//eve//3r3v/s3M3/7NzN/+zczf+pdD/KqXQ/yql0P8oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAACwekIesHpCHrB6Qh64hVH/uIVR/7iFUf/+/Pn//vz5//78+f/53L7/+dy+//ncvv/4 - 277/+Nu+//jbvv/43L//+Ny///jcv//528H/+dvB//nbwf/53MD/+dzA//ncwP/53cH/+d3B//ndwf/6 - 3cL/+t3C//rdwv/759T/++fU//vn1P/17eL/9e3i//Xt4v+wekLksHpC5LB6QuQAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwekIesHpCHrB6Qh64hVH/uIVR/7iFUf/+/Pn//vz5//78+f/5 - 3L7/+dy+//ncvv/4277/+Nu+//jbvv/43L//+Ny///jcv//528H/+dvB//nbwf/53MD/+dzA//ncwP/5 - 3cH/+d3B//ndwf/63cL/+t3C//rdwv/759T/++fU//vn1P/17eL/9e3i//Xt4v+wekLksHpC5LB6QuQA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwekIesHpCHrB6Qh64hVH/uIVR/7iFUf/+ - /Pn//vz5//78+f/53L7/+dy+//ncvv/4277/+Nu+//jbvv/43L//+Ny///jcv//528H/+dvB//nbwf/5 - 3MD/+dzA//ncwP/53cH/+d3B//ndwf/63cL/+t3C//rdwv/759T/++fU//vn1P/17eL/9e3i//Xt4v+w - ekLksHpC5LB6QuQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC2gUYJtoFGCbaBRgm4 - hEr/uIRK/7iESv/++/f//vv3//779//53MD/+dzA//ncwP/43L7/+Ny+//jcvv/43L7/+Ny+//jcvv/4 - 27//+Nu///jbv//53b//+d2///ndv//53b//+d2///ndv//53cL/+d3C//ndwv/74sv/++LL//viy//8 - +fX//Pn1//z59f+2gUb7toFG+7aBRvu2gUYBtoFGAbaBRgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC2 - gUYJtoFGCbaBRgm4hEr/uIRK/7iESv/++/f//vv3//779//53MD/+dzA//ncwP/43L7/+Ny+//jcvv/4 - 3L7/+Ny+//jcvv/427//+Nu///jbv//53b//+d2///ndv//53b//+d2///ndv//53cL/+d3C//ndwv/7 - 4sv/++LL//viy//8+fX//Pn1//z59f+2gUb7toFG+7aBRvu2gUYBtoFGAbaBRgEAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAC2gUYJtoFGCbaBRgm4hEr/uIRK/7iESv/++/f//vv3//779//53MD/+dzA//ncwP/4 - 3L7/+Ny+//jcvv/43L7/+Ny+//jcvv/427//+Nu///jbv//53b//+d2///ndv//53b//+d2///ndv//5 - 3cL/+d3C//ndwv/74sv/++LL//viy//8+fX//Pn1//z59f+2gUb7toFG+7aBRvu2gUYBtoFGAbaBRgEA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8h0r5vIdK+byHSvn89vD//Pbw//z28P/5 - 38f/+d/H//nfx//53Lz/+dy8//ncvP/63L7/+ty+//rcvv/628D/+tvA//rbwP/63cL/+t3C//rdwv/6 - 3cH/+t3B//rdwf/53cP/+d3D//ndw//74Mn/++DJ//vgyf///Pr///z6///8+v/AjFL/wIxS/8CMUv+8 - h0oPvIdKD7yHSg8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8h0r5vIdK+byHSvn8 - 9vD//Pbw//z28P/538f/+d/H//nfx//53Lz/+dy8//ncvP/63L7/+ty+//rcvv/628D/+tvA//rbwP/6 - 3cL/+t3C//rdwv/63cH/+t3B//rdwf/53cP/+d3D//ndw//74Mn/++DJ//vgyf///Pr///z6///8+v/A - jFL/wIxS/8CMUv+8h0oPvIdKD7yHSg8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 - h0r5vIdK+byHSvn89vD//Pbw//z28P/538f/+d/H//nfx//53Lz/+dy8//ncvP/63L7/+ty+//rcvv/6 - 28D/+tvA//rbwP/63cL/+t3C//rdwv/63cH/+t3B//rdwf/53cP/+d3D//ndw//74Mn/++DJ//vgyf// - /Pr///z6///8+v/AjFL/wIxS/8CMUv+8h0oPvIdKD7yHSg8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAADDjU3aw41N2sONTdr159j/9efY//Xn2P/65dL/+uXS//rl0v/52rv/+dq7//nau//5 - 27v/+du7//nbu//6277/+tu+//rbvv/63cD/+t3A//rdwP/63cD/+t3A//rdwP/53cP/+d3D//ndw//7 - 4cj/++HI//vhyP///fv///37///9+//Ik1b/yJNW/8iTVv/DjU0Sw41NEsONTRIAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDjU3aw41N2sONTdr159j/9efY//Xn2P/65dL/+uXS//rl0v/5 - 2rv/+dq7//nau//527v/+du7//nbu//6277/+tu+//rbvv/63cD/+t3A//rdwP/63cD/+t3A//rdwP/5 - 3cP/+d3D//ndw//74cj/++HI//vhyP///fv///37///9+//Ik1b/yJNW/8iTVv/DjU0Sw41NEsONTRIA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDjU3aw41N2sONTdr159j/9efY//Xn2P/6 - 5dL/+uXS//rl0v/52rv/+dq7//nau//527v/+du7//nbu//6277/+tu+//rbvv/63cD/+t3A//rdwP/6 - 3cD/+t3A//rdwP/53cP/+d3D//ndw//74cj/++HI//vhyP///fv///37///9+//Ik1b/yJNW/8iTVv/D - jU0Sw41NEsONTRIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADKk1G7ypNRu8qTUbvw - 2cD/8NnA//DZwP/77eH/++3h//vt4f/52r//+dq///nav//53MH/+dzB//ncwf/53sT/+d7E//nexP/6 - 4Mf/+uDH//rgx//64sr/+uLK//riyv/64s3/+uLN//rizf/65dD/+uXQ//rl0P///v3///79///+/f/L - jln/y45Z/8uOWf/Kk1HxypNR8cqTUfHKk1FFypNRRcqTUUUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADK - k1G7ypNRu8qTUbvw2cD/8NnA//DZwP/77eH/++3h//vt4f/52r//+dq///nav//53MH/+dzB//ncwf/5 - 3sT/+d7E//nexP/64Mf/+uDH//rgx//64sr/+uLK//riyv/64s3/+uLN//rizf/65dD/+uXQ//rl0P// - /v3///79///+/f/Ljln/y45Z/8uOWf/Kk1HxypNR8cqTUfHKk1FFypNRRcqTUUUAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAADKk1G7ypNRu8qTUbvw2cD/8NnA//DZwP/77eH/++3h//vt4f/52r//+dq///nav//5 - 3MH/+dzB//ncwf/53sT/+d7E//nexP/64Mf/+uDH//rgx//64sr/+uLK//riyv/64s3/+uLN//rizf/6 - 5dD/+uXQ//rl0P///v3///79///+/f/Ljln/y45Z/8uOWf/Kk1HxypNR8cqTUfHKk1FFypNRRcqTUUUA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQmVSk0JlUpNCZVKTt0LH/7dCx/+3Qsf//9vD///bw///28P/6 - 4cr/+uHK//rhyv/748z/++PM//vjzP/749D/++PQ//vj0P/75tP/++bT//vm0//76dX/++nV//vp1f/8 - 6dj//OnY//zp2P/86tv//Orb//zq2/////3////9/////f/SnHD/0pxw/9KccP/u2cD/7tnA/+7ZwP/Q - mVTl0JlU5dCZVOUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQmVSk0JlUpNCZVKTt0LH/7dCx/+3Qsf// - 9vD///bw///28P/64cr/+uHK//rhyv/748z/++PM//vjzP/749D/++PQ//vj0P/75tP/++bT//vm0//7 - 6dX/++nV//vp1f/86dj//OnY//zp2P/86tv//Orb//zq2/////3////9/////f/SnHD/0pxw/9KccP/u - 2cD/7tnA/+7ZwP/QmVTl0JlU5dCZVOUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQmVSk0JlUpNCZVKTt - 0LH/7dCx/+3Qsf//9vD///bw///28P/64cr/+uHK//rhyv/748z/++PM//vjzP/749D/++PQ//vj0P/7 - 5tP/++bT//vm0//76dX/++nV//vp1f/86dj//OnY//zp2P/86tv//Orb//zq2/////3////9/////f/S - nHD/0pxw/9KccP/u2cD/7tnA/+7ZwP/QmVTl0JlU5dCZVOUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADV - nleS1Z5XktWeV5LryqT/68qk/+vKpP///fv///37///9+//96dX//enV//3p1f/969j//evY//3r2P/9 - 6tv//erb//3q2//97d///e3f//3t3//98OL//fDi//3w4v/98eT//fHk//3x5P/88OT//PDk//zw5P// - ///////////////gn2//4J9v/+Cfb///+/n///v5///7+f/ft4b/37eG/9+3hv8AAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAADVnleS1Z5XktWeV5LryqT/68qk/+vKpP///fv///37///9+//96dX//enV//3p1f/9 - 69j//evY//3r2P/96tv//erb//3q2//97d///e3f//3t3//98OL//fDi//3w4v/98eT//fHk//3x5P/8 - 8OT//PDk//zw5P/////////////////gn2//4J9v/+Cfb///+/n///v5///7+f/ft4b/37eG/9+3hv8A - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADVnleS1Z5XktWeV5LryqT/68qk/+vKpP///fv///37///9+//9 - 6dX//enV//3p1f/969j//evY//3r2P/96tv//erb//3q2//97d///e3f//3t3//98OL//fDi//3w4v/9 - 8eT//fHk//3x5P/88OT//PDk//zw5P/////////////////gn2//4J9v/+Cfb///+/n///v5///7+f/f - t4b/37eG/9+3hv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADao1qE2qNahNqjWoTrxZn/68WZ/+vFmf// - ///////////////87+L//O/i//zv4v/98Of//fDn//3w5//98ev//fHr//3x6//99e7//fXu//317v/9 - +PH//fjx//348f/9+vf//fr3//369////Pr///z6///8+v/////////////////++/f//vv3//779//0 - 2r//9Nq///Tav//ao1rq2qNa6tqjWuoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADao1qE2qNahNqjWoTr - xZn/68WZ/+vFmf/////////////////87+L//O/i//zv4v/98Of//fDn//3w5//98ev//fHr//3x6//9 - 9e7//fXu//317v/9+PH//fjx//348f/9+vf//fr3//369////Pr///z6///8+v/////////////////+ - +/f//vv3//779//02r//9Nq///Tav//ao1rq2qNa6tqjWuoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADa - o1qE2qNahNqjWoTrxZn/68WZ/+vFmf/////////////////87+L//O/i//zv4v/98Of//fDn//3w5//9 - 8ev//fHr//3x6//99e7//fXu//317v/9+PH//fjx//348f/9+vf//fr3//369////Pr///z6///8+v// - ///////////////++/f//vv3//779//02r//9Nq///Tav//ao1rq2qNa6tqjWuoAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAADep1xt3qdcbd6nXG3qv4v/6r+L/+q/i/////////////////////////////////// - ///////////////////////////////9+fT//fn0//359P/78+r/+/Pq//vz6v/469n/+OvZ//jr2f/4 - 5tP/+ObT//jm0//138X/9d/F//Xfxf/py6X/6cul/+nLpf/ep1zt3qdc7d6nXO3ep1xd3qdcXd6nXF0A - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADep1xt3qdcbd6nXG3qv4v/6r+L/+q/i/////////////////// - ///////////////////////////////////////////////9+fT//fn0//359P/78+r/+/Pq//vz6v/4 - 69n/+OvZ//jr2f/45tP/+ObT//jm0//138X/9d/F//Xfxf/py6X/6cul/+nLpf/ep1zt3qdc7d6nXO3e - p1xd3qdcXd6nXF0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADep1xt3qdcbd6nXG3qv4v/6r+L/+q/i/// - ///////////////////////////////////////////////////////////////9+fT//fn0//359P/7 - 8+r/+/Pq//vz6v/469n/+OvZ//jr2f/45tP/+ObT//jm0//138X/9d/F//Xfxf/py6X/6cul/+nLpf/e - p1zt3qdc7d6nXO3ep1xd3qdcXd6nXF0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADiq1424qteNuKrXjbi - q17G4qtexuKrXsbqu4D/6ruA/+q7gP/otnb/6LZ2/+i2dv/msWz/5rFs/+axbP/kr2f/5K9n/+SvZ//i - q17w4qte8OKrXvDiq17j4qte4+KrXuPiq17P4qtez+KrXs/iq17M4qtezOKrXsziq1674qteu+KrXrvi - q16o4qteqOKrXqjiq15L4qteS+KrXkviq14F4qteBeKrXgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADi - q1424qteNuKrXjbiq17G4qtexuKrXsbqu4D/6ruA/+q7gP/otnb/6LZ2/+i2dv/msWz/5rFs/+axbP/k - r2f/5K9n/+SvZ//iq17w4qte8OKrXvDiq17j4qte4+KrXuPiq17P4qtez+KrXs/iq17M4qtezOKrXszi - q1674qteu+KrXrviq16o4qteqOKrXqjiq15L4qteS+KrXkviq14F4qteBeKrXgUAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAADiq1424qteNuKrXjbiq17G4qtexuKrXsbqu4D/6ruA/+q7gP/otnb/6LZ2/+i2dv/m - sWz/5rFs/+axbP/kr2f/5K9n/+SvZ//iq17w4qte8OKrXvDiq17j4qte4+KrXuPiq17P4qtez+KrXs/i - q17M4qtezOKrXsziq1674qteu+KrXrviq16o4qteqOKrXqjiq15L4qteS+KrXkviq14F4qteBeKrXgUA - AAAAAD8AAAAAAAAAPwAAAAAAAAA/AAAAAAAAAD8AAAAAAAAAPwAAAAAAAAA/AAAAAAAAAD8AAAAAAAAA - PwAAAAAAAAA/AAAAAAAAAD8AAAAAAAAAPwAAAAAAAAA/AAAAAAAAAD8AAAAAAAAAPwAAAAAAAAA/AADg - AAAAAD8AAOAAAAAAPwAA4AAAAAA/AADgAAAAAD8AAOAAAAAAPwAA4AAAAAA/AADgAAAAAAcAAOAAAAAA - BwAA4AAAAAAHAAD8AAAAAAcAAPwAAAAABwAA/AAAAAAHAAD8AAAAAAcAAPwAAAAABwAA/AAAAAAHAAD8 - AAAAAAAAAPwAAAAAAAAA/AAAAAAAAAD8AAAAAAAAAPwAAAAAAAAA/AAAAAAAAAD8AAAAAAAAAPwAAAAA - AAAA/AAAAAAAAAD8AAAAAAAAAPwAAAAAAAAA/AAAAAAAAAD8AAAAAAAAAPwAAAAAAAAA/AAAAAAAAAD8 - AAAAAAAAAPwAAAAAAAAA/AAAAAAAAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAADDDgAAww4AAAAAAAAA - AAAAj1owFI9aMBSPWjCEj1owhI9aMKOPWjCjj1owto9aMLaPWjDJj1owyY9aMNqPWjDaj1ow649aMOuP - WjD6j1ow+pRgOP+UYDj/mWhA/5loQP+ic07/onNO/6yBXv+sgV7/j1ow2Y9aMNmPWjA0j1owNAAAAAAA - AAAAAAAAAAAAAACPWjAUj1owFI9aMISPWjCEj1owo49aMKOPWjC2j1owto9aMMmPWjDJj1ow2o9aMNqP - WjDrj1ow649aMPqPWjD6lGA4/5RgOP+ZaED/mWhA/6JzTv+ic07/rIFe/6yBXv+PWjDZj1ow2Y9aMDSP - WjA0AAAAAAAAAAAAAAAAAAAAAJNeMmiTXjJot49s/7ePbP/WuaL/1rmi/9/Fsv/fxbL/59TC/+fUwv/u - 39P/7t/T//Xq4v/16uL/+/Tv//v07//9+vb//fr2///+/f///v3/++vf//vr3//77+b/++/m/8Ccf//A - nH//k14yb5NeMm8AAAAAAAAAAAAAAAAAAAAAk14yaJNeMmi3j2z/t49s/9a5ov/WuaL/38Wy/9/Fsv/n - 1ML/59TC/+7f0//u39P/9eri//Xq4v/79O//+/Tv//369v/9+vb///79///+/f/769//++vf//vv5v/7 - 7+b/wJx//8Ccf/+TXjJvk14ybwAAAAAAAAAAAAAAAAAAAACYYzWJmGM1icejhP/Ho4T///////////// - /////////////////////////////////vz///78//779//++/f//vfx//738f/+9vH//vbx/+Sthf/k - rYX/+ujb//ro2//OrpT/zq6U/5hjNYuYYzWLAAAAAAAAAAAAAAAAAAAAAJhjNYmYYzWJx6OE/8ejhP// - ///////////////////////////////////////////+/P///vz//vv3//779//+9/H//vfx//728f/+ - 9vH/5K2F/+Sthf/66Nv/+ujb/86ulP/OrpT/mGM1i5hjNYsAAAAAAAAAAAAAAAAAAAAAnWg4V51oOFed - aDj2nWg49rOEWP+zhFj/2aR6/9mkev/YnW7/2J1u/9eaaf/Xmmn/2JVi/9iVYv/WkVz/1pFc/9SOWP/U - jlj/041W/9ONVv/inGj/4pxo//rj0f/649H/2Lqh/9i6of+daDienWg4ngAAAAAAAAAAAAAAAAAAAACd - aDhXnWg4V51oOPadaDj2s4RY/7OEWP/ZpHr/2aR6/9idbv/YnW7/15pp/9eaaf/YlWL/2JVi/9aRXP/W - kVz/1I5Y/9SOWP/TjVb/041W/+KcaP/inGj/+uPR//rj0f/YuqH/2Lqh/51oOJ6daDieAAAAAAAAAAAA - AAAAAAAAAKNuOxSjbjsUo247q6NuO6vVrYv/1a2L//3w5f/98OX/98eh//fHof/3z6z/98+s//nVtP/5 - 1bT/+Nq8//javP/43sH/+N7B//rhxf/64cX/+uTM//rkzP/99ez//fXs/+LOuf/izrn/o247s6NuO7MA - AAAAAAAAAAAAAAAAAAAAo247FKNuOxSjbjuro247q9Wti//VrYv//fDl//3w5f/3x6H/98eh//fPrP/3 - z6z/+dW0//nVtP/42rz/+Nq8//jewf/43sH/+uHF//rhxf/65Mz/+uTM//317P/99ez/4s65/+LOuf+j - bjuzo247swAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKl0PyipdD8otoVV/7aFVf/+/v3//v79//rewf/6 - 3sH/+ty+//rcvv/527//+du///nbv//527//+d3A//ndwP/627//+tu///rcwv/63ML//eve//3r3v/s - 3M3/7NzN/6l0P8qpdD/KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqXQ/KKl0Pyi2hVX/toVV//7+/f/+ - /v3/+t7B//rewf/63L7/+ty+//nbv//527//+du///nbv//53cD/+d3A//rbv//627//+tzC//rcwv/9 - 697//eve/+zczf/s3M3/qXQ/yql0P8oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwekIesHpCHriFUf+4 - hVH//vz5//78+f/53L7/+dy+//jbvv/4277/+Ny///jcv//528H/+dvB//ncwP/53MD/+d3B//ndwf/6 - 3cL/+t3C//vn1P/759T/9e3i//Xt4v+wekLksHpC5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALB6Qh6w - ekIeuIVR/7iFUf/+/Pn//vz5//ncvv/53L7/+Nu+//jbvv/43L//+Ny///nbwf/528H/+dzA//ncwP/5 - 3cH/+d3B//rdwv/63cL/++fU//vn1P/17eL/9e3i/7B6QuSwekLkAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAtoFGCbaBRgm4hEr/uIRK//779//++/f/+dzA//ncwP/43L7/+Ny+//jcvv/43L7/+Nu///jbv//5 - 3b//+d2///ndv//53b//+d3C//ndwv/74sv/++LL//z59f/8+fX/toFG+7aBRvu2gUYBtoFGAQAAAAAA - AAAAAAAAAAAAAAC2gUYJtoFGCbiESv+4hEr//vv3//779//53MD/+dzA//jcvv/43L7/+Ny+//jcvv/4 - 27//+Nu///ndv//53b//+d2///ndv//53cL/+d3C//viy//74sv//Pn1//z59f+2gUb7toFG+7aBRgG2 - gUYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvIdK+byHSvn89vD//Pbw//nfx//538f/+dy8//ncvP/6 - 3L7/+ty+//rbwP/628D/+t3C//rdwv/63cH/+t3B//ndw//53cP/++DJ//vgyf///Pr///z6/8CMUv/A - jFL/vIdKD7yHSg8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8h0r5vIdK+fz28P/89vD/+d/H//nfx//5 - 3Lz/+dy8//rcvv/63L7/+tvA//rbwP/63cL/+t3C//rdwf/63cH/+d3D//ndw//74Mn/++DJ///8+v// - /Pr/wIxS/8CMUv+8h0oPvIdKDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMONTdrDjU3a9efY//Xn2P/6 - 5dL/+uXS//nau//52rv/+du7//nbu//6277/+tu+//rdwP/63cD/+t3A//rdwP/53cP/+d3D//vhyP/7 - 4cj///37///9+//Ik1b/yJNW/8ONTRLDjU0SAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw41N2sONTdr1 - 59j/9efY//rl0v/65dL/+dq7//nau//527v/+du7//rbvv/6277/+t3A//rdwP/63cD/+t3A//ndw//5 - 3cP/++HI//vhyP///fv///37/8iTVv/Ik1b/w41NEsONTRIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADK - k1G7ypNRu/DZwP/w2cD/++3h//vt4f/52r//+dq///ncwf/53MH/+d7E//nexP/64Mf/+uDH//riyv/6 - 4sr/+uLN//rizf/65dD/+uXQ///+/f///v3/y45Z/8uOWf/Kk1HxypNR8cqTUUXKk1FFAAAAAAAAAAAA - AAAAAAAAAMqTUbvKk1G78NnA//DZwP/77eH/++3h//nav//52r//+dzB//ncwf/53sT/+d7E//rgx//6 - 4Mf/+uLK//riyv/64s3/+uLN//rl0P/65dD///79///+/f/Ljln/y45Z/8qTUfHKk1HxypNRRcqTUUUA - AAAAAAAAAAAAAAAAAAAA0JlUpNCZVKTt0LH/7dCx///28P//9vD/+uHK//rhyv/748z/++PM//vj0P/7 - 49D/++bT//vm0//76dX/++nV//zp2P/86dj//Orb//zq2/////3////9/9KccP/SnHD/7tnA/+7ZwP/Q - mVTl0JlU5QAAAAAAAAAAAAAAAAAAAADQmVSk0JlUpO3Qsf/t0LH///bw///28P/64cr/+uHK//vjzP/7 - 48z/++PQ//vj0P/75tP/++bT//vp1f/76dX//OnY//zp2P/86tv//Orb/////f////3/0pxw/9KccP/u - 2cD/7tnA/9CZVOXQmVTlAAAAAAAAAAAAAAAAAAAAANWeV5LVnleS68qk/+vKpP///fv///37//3p1f/9 - 6dX//evY//3r2P/96tv//erb//3t3//97d///fDi//3w4v/98eT//fHk//zw5P/88OT////////////g - n2//4J9v///7+f//+/n/37eG/9+3hv8AAAAAAAAAAAAAAAAAAAAA1Z5XktWeV5LryqT/68qk///9+/// - /fv//enV//3p1f/969j//evY//3q2//96tv//e3f//3t3//98OL//fDi//3x5P/98eT//PDk//zw5P// - /////////+Cfb//gn2////v5///7+f/ft4b/37eG/wAAAAAAAAAAAAAAAAAAAADao1qE2qNahOvFmf/r - xZn////////////87+L//O/i//3w5//98Of//fHr//3x6//99e7//fXu//348f/9+PH//fr3//369/// - /Pr///z6/////////////vv3//779//02r//9Nq//9qjWurao1rqAAAAAAAAAAAAAAAAAAAAANqjWoTa - o1qE68WZ/+vFmf////////////zv4v/87+L//fDn//3w5//98ev//fHr//317v/99e7//fjx//348f/9 - +vf//fr3///8+v///Pr////////////++/f//vv3//Tav//02r//2qNa6tqjWuoAAAAAAAAAAAAAAAAA - AAAA3qdcbd6nXG3qv4v/6r+L/////////////////////////////////////////////fn0//359P/7 - 8+r/+/Pq//jr2f/469n/+ObT//jm0//138X/9d/F/+nLpf/py6X/3qdc7d6nXO3ep1xd3qdcXQAAAAAA - AAAAAAAAAAAAAADep1xt3qdcbeq/i//qv4v////////////////////////////////////////////9 - +fT//fn0//vz6v/78+r/+OvZ//jr2f/45tP/+ObT//Xfxf/138X/6cul/+nLpf/ep1zt3qdc7d6nXF3e - p1xdAAAAAAAAAAAAAAAAAAAAAOKrXjbiq1424qtexuKrXsbqu4D/6ruA/+i2dv/otnb/5rFs/+axbP/k - r2f/5K9n/+KrXvDiq17w4qte4+KrXuPiq17P4qtez+KrXsziq17M4qteu+KrXrviq16o4qteqOKrXkvi - q15L4qteBeKrXgUAAAAAAAAAAAAAAAAAAAAA4qteNuKrXjbiq17G4qtexuq7gP/qu4D/6LZ2/+i2dv/m - sWz/5rFs/+SvZ//kr2f/4qte8OKrXvDiq17j4qte4+KrXs/iq17P4qtezOKrXsziq1674qteu+KrXqji - q16o4qteS+KrXkviq14F4qteBQAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA/A - AAAPwAAAD8AAAA/AAAAPwAAAA8AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAAPAAAADwAAAA8AAAAPAAAADw - AAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAAKAAAABAAAAAgAAAAAQAgAAAAAAAABAAAww4AAMMOAAAA - AAAAAAAAAI9aMBSPWjCEj1owo49aMLaPWjDJj1ow2o9aMOuPWjD6lGA4/5loQP+ic07/rIFe/49aMNmP - WjA0AAAAAAAAAACTXjJot49s/9a5ov/fxbL/59TC/+7f0//16uL/+/Tv//369v///v3/++vf//vv5v/A - nH//k14ybwAAAAAAAAAAmGM1icejhP////////////////////////78//779//+9/H//vbx/+Sthf/6 - 6Nv/zq6U/5hjNYsAAAAAAAAAAJ1oOFedaDj2s4RY/9mkev/YnW7/15pp/9iVYv/WkVz/1I5Y/9ONVv/i - nGj/+uPR/9i6of+daDieAAAAAAAAAACjbjsUo247q9Wti//98OX/98eh//fPrP/51bT/+Nq8//jewf/6 - 4cX/+uTM//317P/izrn/o247swAAAAAAAAAAAAAAAKl0Pyi2hVX//v79//rewf/63L7/+du///nbv//5 - 3cD/+tu///rcwv/9697/7NzN/6l0P8oAAAAAAAAAAAAAAACwekIeuIVR//78+f/53L7/+Nu+//jcv//5 - 28H/+dzA//ndwf/63cL/++fU//Xt4v+wekLkAAAAAAAAAAAAAAAAtoFGCbiESv/++/f/+dzA//jcvv/4 - 3L7/+Nu///ndv//53b//+d3C//viy//8+fX/toFG+7aBRgEAAAAAAAAAAAAAAAC8h0r5/Pbw//nfx//5 - 3Lz/+ty+//rbwP/63cL/+t3B//ndw//74Mn///z6/8CMUv+8h0oPAAAAAAAAAAAAAAAAw41N2vXn2P/6 - 5dL/+dq7//nbu//6277/+t3A//rdwP/53cP/++HI///9+//Ik1b/w41NEgAAAAAAAAAAAAAAAMqTUbvw - 2cD/++3h//nav//53MH/+d7E//rgx//64sr/+uLN//rl0P///v3/y45Z/8qTUfHKk1FFAAAAAAAAAADQ - mVSk7dCx///28P/64cr/++PM//vj0P/75tP/++nV//zp2P/86tv////9/9KccP/u2cD/0JlU5QAAAAAA - AAAA1Z5XkuvKpP///fv//enV//3r2P/96tv//e3f//3w4v/98eT//PDk///////gn2////v5/9+3hv8A - AAAAAAAAANqjWoTrxZn///////zv4v/98Of//fHr//317v/9+PH//fr3///8+v///////vv3//Tav//a - o1rqAAAAAAAAAADep1xt6r+L///////////////////////9+fT/+/Pq//jr2f/45tP/9d/F/+nLpf/e - p1zt3qdcXQAAAAAAAAAA4qteNuKrXsbqu4D/6LZ2/+axbP/kr2f/4qte8OKrXuPiq17P4qtezOKrXrvi - q16o4qteS+KrXgUAAwAAAAMAAAADAAAAAwAAAAMAAIADAACAAwAAgAEAAMABAADAAQAAwAAAAMAAAADA - AAAAwAAAAMAAAADAAAAA - - - \ No newline at end of file diff --git a/Novetus/Novetus.ClientScriptTester/Novetus.ClientScriptTester.csproj b/Novetus/Novetus.ClientScriptTester/Novetus.ClientScriptTester.csproj deleted file mode 100644 index bb378aa..0000000 --- a/Novetus/Novetus.ClientScriptTester/Novetus.ClientScriptTester.csproj +++ /dev/null @@ -1,113 +0,0 @@ - - - - - Debug - AnyCPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0} - WinExe - Novetus.ClientScriptTester - ClientScriptTester - v4.8 - 512 - - - - AnyCPU - true - full - false - bin\Debug\ - TRACE;DEBUG;TESTER;NOVETUS_APPS - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE;TESTER;NOVETUS_APPS;NET481 - prompt - 4 - false - - - NovetusIcon.ico - - - app.manifest - - - - - - - - - - - - - - - - - - - - - - Form - - - ClientScriptTestForm.cs - - - - - ClientScriptTestForm.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - SET path=$(SolutionDir)build -if not exist "%25path%25" mkdir "%25path%25" -SET path2=%25path%25\ClientScriptTester -if not exist "%25path2%25" mkdir "%25path2%25" -copy $(ProjectDir)$(OutDir) "%25path2%25"\* -del "%25path%25"\$(TargetName).vshost.exe -del "%25path%25"\$(TargetName).vshost.exe.config -del "%25path%25"\$(TargetName).vshost.exe.manifest -del "%25path%25"\$(TargetName).xml - - - - - - \ No newline at end of file diff --git a/Novetus/Novetus.ClientScriptTester/NovetusIcon.ico b/Novetus/Novetus.ClientScriptTester/NovetusIcon.ico deleted file mode 100644 index 8cd1cbe06cb36d095d96e779d231450933909936..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 135503 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 -// 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 Novetus.ClientScriptTester.Properties { - using System; - - - ///

- /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Novetus.ClientScriptTester.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} diff --git a/Novetus/Novetus.ClientScriptTester/Properties/Resources.resx b/Novetus/Novetus.ClientScriptTester/Properties/Resources.resx deleted file mode 100644 index af7dbeb..0000000 --- a/Novetus/Novetus.ClientScriptTester/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/Novetus/Novetus.ClientScriptTester/Properties/Settings.Designer.cs b/Novetus/Novetus.ClientScriptTester/Properties/Settings.Designer.cs deleted file mode 100644 index 42f97fc..0000000 --- a/Novetus/Novetus.ClientScriptTester/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// 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 Novetus.ClientScriptTester.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.2.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - } -} diff --git a/Novetus/Novetus.ClientScriptTester/Properties/Settings.settings b/Novetus/Novetus.ClientScriptTester/Properties/Settings.settings deleted file mode 100644 index 3964565..0000000 --- a/Novetus/Novetus.ClientScriptTester/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Novetus/Novetus.ClientScriptTester/Resources/ClientScriptTester.ico b/Novetus/Novetus.ClientScriptTester/Resources/ClientScriptTester.ico deleted file mode 100644 index ced545e2084f44c14e9270424044dc6596af0a83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101595 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 CoDxO= diff --git a/Novetus/Novetus.ClientScriptTester/Resources/NovetusIcon.ico b/Novetus/Novetus.ClientScriptTester/Resources/NovetusIcon.ico deleted file mode 100644 index 8cd1cbe06cb36d095d96e779d231450933909936..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 135503 zcmdQ~1ydYdu$^6;Ad9Un*)FEjj79{9RgGbRAvtsoeV&id{FUq4cW$|H~oNy1;RDX;z!TWERV&_r)P{?T;z(rHs5tdh9C$4O%Cai zVXI@y4aOSl-5n&yezq?N+cZ*gyjfbA{re`X*OCl$Ajw#}M#fmHx*UXX8ltrnqM;VC zG#_%J?n|8z?#jKnb%NXO{-r%Tt!zDBm84wuAZ#so*-Oe<2_JAd>Rq|3=lXb|x1>EF zc!xSoXB86~cjk4Kk(GZF3+Jw8fS?=crG^9a5O8g8tfnU+vW%zl85!}>H7tB_Y%7*ZSBTy!OBu%lNaoZjX)ZrWf|(j5<)vO z;mjgI4decuJ@}G?6q#leZybl7gqi@UM3%J#IB~JVDh7A*_!^oG0iymO#D<_Z?$|6UXcT=SDtNDi<|JoQjOYh>*X444T1plo11Ec zhUAl%D=j;>qmM`DE9b3T4i~v9Y{L9IZxUw!;Md5o<9w?fiKx${Hi{GWS%5kc9|QL- z`TPn`(C^zt=RbeD=&=y6o040GjYM2bkT_)~GF-X}7-+;Fgn93I5&&dyFjO@LtcVT( zsBTkBLjs=s!8FnM1z+Zt&HZTiZeav{&nl7#yWhZGH5y{GV?So~4T`r{Oyk0SOlYUa z-9?Ac#xol40=?h>(bX9_0{7Hb4Gx&=mXHu^9fIUi; zVGI@Ej`ia^g-~*k+$#AH^$GRr8%l9etK;@ooNa~~D3uY57fmawO0!&Rawk%Dz&u*H z=HPD&?5LhT_E^7SXt8Ey^LmZa%474+u>A$_j_kdO#0%I9_{TUe)G9MS8;cj3F!fQa zWHyuJy$K5h;1g&Sc#S-Y9-D?Zo8il|MEHbSCAZZuUi`N5Jl+uIsI1l_fYD5oi;AKx z!W!qEZwP=!)@giT0kEf-a!UzVt;9pnR~IBg0pUXx)*$lKm1B(Q*j9(^k)7AqZe3JN0YIItX7`CE~ zag@|L@ZDALpL-mYF3!Gq7zkL;0R3eE9Wh628ejF?Sb^{g%&mkVq7?iAC{pIQY7zMh zvTY09E{FbCje)J$t6LOe;hIp)hxY*zk+jJ4^3j8~J@PZ0@TQY?XmMZun-4}K1ku}GmRhXuo=9AI7Hz2b&V}Ty#$kp~LPx@D zxlQ0yc|1MaTJJO|4JAtipx`&I4_G`wzExlZFn~$=bvItRasesxK2gd4>~?f%S27d7 z#NP1x+=WeA06y>BR3dmJ7br>y?iq zA()uy4j4|&7yxZZV2ri7Hl=dS^X55Y%P@xNUGX`JN|H&016UJXz}eIf6VAh30WH9M z>#hlDt#fRj* zmWN|En9)m# z)MJKv)KoB3FWE^uygwuP?~U zIr6r$gr%b&7zp*rhQ|8&C8>_wJaYbK)>PJH0|G0#RPCE{nCrZ}6Qum_7OkIqgb~47 zGp^_-j8Qa3u`?xN+%My2s2}qqn|HGZWgMR`WJmYxFZ5JI*!()#MA$yJ{X>abch}lYZQc-vgoPD84oQ%GBIx1t%P$0*w>Cn zLJ(O-QxDk#z?0c*M3rNDgLTnl*zj)0=GRs?`_o+r*YYl2hPUmeHGmDrfmVUz7LmEq z@{E8^YY-_%?(51KQ;aGCWgsz%CRnNt^}wh6g_9})S#dYC{FwIRZ!c!domi@p+|KYpc@XB3$Jak7;g>8NzrNs0Ytx z_T=9t647FGnW6y8p!x!2^p{ogJ+@HheT6gwe8M?&Bq2Oe%|5BnqO&8mbQ4Zn4;55( z8b1{!lUIio;ziChqQyJey2h3&f2=jN0|xMyIQ~Vb>{pA*&->@bC&AIwwKj~{du$V~ zXQ1G{IdiwSZyV4fQ=#StAk{z&xEg_)5;go6xiJqgu<6Q)iR6ZhK8E&lI7IB)b!q^q1XYgB1Ya>oKGEuywra;s%qm7ZQ8d2s*9hV_;}8FI%Xb^4=IbQ0c#UAdc_$1+V8V)^gdT@*=?r~3+@%GUS(UHyaA#R^|Z8qd^p9X zzlcpJDD&R&pR#CE$kpZWZD8sRw~@a{wM=hqvYNVML#@Q2QsI3mkGsN%rE2X#L|D|t zYSI)nb^0tI$7!3%`1Oy{x@{6s&3CD`3E6+iE7bMa@A!qE?Tj4m&Z%;BjjE*BRi1mB z3C3=Mb$Hl`SK<%H&erc@v$oy@e0(eizZunrdVg&X;k zSkwzz-@j2E#B{4AY~1O$mObCpCR|#y)L!w_2N|F#(N>CCexZJobtF9a-mgEy_=fLe z;|U!rk3_FIO>!^oFxnp}sxo45q8Dv-`lzCb?!bZ4>60R4jA?rZBPtggX}Ob7sYXSI z)Rc!M;Zv$Tsww=<)E`d$z`Zv`h`|~`m1UU&&PH+uwY5CDzSL4RpInY{lOE+?VI0Sz zzdJoI-A0?O3*;|v7}LyF!Y`ydd^j*ZU<6~UlkYDGb~k+4)Eik6QhoTGc)rqwtc(Zw zWrDzFeD_5+m3s?-;>(L7#PyM`YT?y5tQet+mb!MZn&rq;3SQP0I{!Y-IynqQPlK7< z8X3vpGzi(vrQ?YGV|_IB)W%nhQ8@~vTuZ&!r2Z_$$+tzV;uAeIHXyP9x@73YgQF>u zpVa*i?tkxZpvia&Jy^K^HgrpZY+aLp*X>zhp62Y<{5@nmm{ZbBvUIT0pT#iTiJD2W zP+e{C}|vn(;Z3U zf}1%yo;jMyd6b~~$#PL*3dJcBWKWp(*8ZoyD6=p9);UvK*2je$PqrmW`n*9NM_`(Y zTT1FF%iLFANyy2Xy@+fRhwyGLg~{N(8S`=O!XdHt_VQ`#&hyZF3bC4A3TJ7j3@4hj zdH?APqu?v2msl{RpM-HJWqR*ohd9)0aQJ`ri4Vh+K@MG%#fe2~04b{b;>iky44n*e zF@<8dSB2EVcf4>LRRTOvKY`PDvm-dDFc00;4hKu#_D&TZG2dx~)=J56PGs3g^{H`* z;78Q*=l*VqUp58uH#hVPg^2~Xl^>hHa4Q6q6oLjQ4Ed$uRinXYm)N*@tMSnBpNm78 z;z+X}3ta_U_&Ymcllr zk)@=Cw$ z5dh4?d_{qAsmIJDqK!`Yyfvm00v^>;2u5^)@1hxNJx*BwA+lwP>*`u2W~^EReh4V- zRT1D?NuTM9p=I`oDsO=cKJ++xZS;^IDd=4i`+_%Zg=72SWvKk0#h0dLls)NJcsH)j z!oe1>v=5!Z%(}FVn0pFY1s_08xQQ63vOYN5Cv3QF@nnpt0CRBgknti6Spmy282G>r zCC%Bq*EoWslX7QDoBNTF(X`9b$uxt`S`4Bk-6D*#^Jch8MwTd6&O1oN%?spxIwR7f zj@I!1IGVm1hE-gSC%%HNr-zhx0hfeS1)x7YGj#;~NH`;U7@XX#>*$)w{}!HnXe98i zXEN@_n-KX-lt2Dt&A{qqZ+LqQcF%_9x}pZ&*%sxauN+mKXxHekA_=Bz>3|ME1`}0M z9Gt{G4X^BRYL%(n&7C;3x0FBj+lk~9cPlu8Nubqj}>0N%FPz>tDzk};km)Om_CDfm7ua)VTxE`lhlmT%Qq;`U*O zm_lrmLehOE+cQ;>84rRHt4Qw8i_6dhBzUkYK~q;4o`$vjJ*Pk>#^@!otBH^_EO8YI zl{|o3Q4F8J!4z=g6D`IXWz(LW{#rdgoz48&q1f@zD{{nV^D>!giMZ=PXSlqJ(&T?lY3vTHI`S zUI62tZ1@45Yd0H)CpKA4*_#+1MvS|lXdxAzc7R(W>SeIVwe?-`;uvFV#p+wR;@$k2 zebd$b=ZpTsj7sDa4+^oTYsS)ST%=+ZBaQ5ssiSBE@gG}Eo++LEm?4B2HzF_u5$*> zdX3)+q}n3L#>Q_y?cTa%!7z}&cEqgB2tl!ob#q;!9FE2g-PZW7b&s2Feyh&!jG(6GMl(WZv%m%o9&N$q{?_yYm-Z0;t0v)OpukgcF3AKrY#_Zp{?@ z^~V&J5!|On6|e@fai>e;8GoL_v$u(FHx4T}eBE0p5^we)sOw~p?6n|*4h#t?xPh%~#K(@z`4@+~}24&2OLz77t^ zlO-iZ{RO5kqWc$-%GBjpF?n004({fQq`1a0Ykx6Y@`IWembCF&b_zy)MqVgNo2K8C8Cpb3H8Rb*t zb>EQwzTS0vVJ^GVE-mlq-P=8y*73XPe3Ox|c-}aGETiKEEl;b-1<>7q%s4=%!Vu5= zRI6MWz}%jW^>Q4MTAW(sf>-_2`D4XK>*17~z~War@2GS!Oyv(oI->=$GWXB(lM+ch zH10gnl*K?bf$wvn%-~f84$MNT;!WltIC|_9T|i~~7CMSh9qDLoq?O%MXLNR$nd-1P z#pS(##Aw<9JSi1LubgH(HL5C38A`zsmFu*Tu_flvnk&*HLjo)4-8~v7#Dq`zwbDN& zCq(2h52R%}{L&#Np@_Cm2*I$*O|*}XxfjW%0- z3eg}lgXg_O?VJ3#hUR~kPxA4?o>J)xoFZL{HvO#n5AOEoAD6?zg%6umJe zpaz>|9q^sdd#{1!pA2y(E=@Vc{OcPIZI}e<^bq~-eLKK!V&v&x34McZTwCO?OkqKj z*3bKtPPX*dL8AtFHvP7So&sUS@R^igpW*#0WQuRfgB(R)E6j8fcB;1YwDWU3)CgP1 zRFA}Hns(E!|9mpR2{h<*;0BhEFU$x6I~aJ2TI|W$!`TIy`*a9wv%^YXsqJ-4LNHxi zYWpt;|4d>4c8{v2&%~5bY5Jx|R((;RzG|DXLP!-fH_#Jq>z8wegj`ZPG}=g{-C1V5 zPyH>!*GxJwBA7ODfAYlB7B#k~?=SgdK2(R$YTD`8bA^xVufxS8<>#6f>Tw9N$xwoy z>MD%SQ0Q=3+T8_DM1cx;~!W3(5k&cjL4{t7Ye1tr`MjiQExwq7OWfw zyy=eh2x!~xmGCPl-Y!X4_u?sJ(ZuJwPVWQoCno;RFn{o^JSVT57cZMLEsOs{_9}Sq zTPYy`Xt2`q3dy>v`|H78zdic-DLD!u2D|GbTOBJan2L%)E!inZHxl6<-&HJ*mwy*^ zT=)X-c2c-xyu3#b%;-bYfn=bKD3M7CF#3h|4@cds&An=?9-nZj+tE{b3cnI0r5XQX zI*MJpk_n4$+hcuoi(B_)}+WZ+Wx$TfhLItlndruMHS?it_7s z>0|VRRSz=p-T&B8tBh65>9X25)R0*Am}`^QVT3sA=3nI~D4}e+N%nl!Ry0TCEgT|o z`b>r8_>F4{dh5r$BunW#x<@Z`Hp`Ny^7%N4*L2M&2qiPRfAE1cKYXkMvwU0&ob?tx zWX;r1sOLnWs`K}uEqxz#<6X^+*c-h1E`?u!)ZSB;qH4E%vju)3U& za(iTc1|46iTi%g)jV}ol9kkHgN9@?o?RvfOo~$dkCq%s747X_XW|r=uQ7G~cts6Y{ zeiD~ONqmjg{?}FI0;X^C7a2YWHebj7=`SNLm<12U;Wt*CvE(mPMwXGVm$YacOLx`z zsL(SnqY)Af*5l|`_&z6Wia+vWWwbqoNEA^jo4aJ|#-fbV#=rrC+tCC=562I$pt9Ei z(gQ0OYsF$7f467wnH;h`Kl8TnxgAD;|72Xh=Kv0GQ1M23URB92IwH_f4tGF^znj0&+z3}JDEe+s51aL@&^NwEN6;d&1!6~S{kwc3urRuY-+~amwx&~W zU*-;JO!vs562SG)@c1{8-`W@~)CPqGRR%)((#G~L+p|W_!#I8B92FJe|)9 zncvYWe|LcS8un7JxlJuDr=DS#JIqJ1u)}KTY$8FFy8IZo-SQoU({WKufHmqPenUZ& z{Td=zn7c+A=*J2JQ(se) z!2Z4gccb5Ve{ikz{^%A?dzr3F7!hbhf}L}fF(bPk&HK9A_+3TAFkvm-OUq$P=|8&z z!#!3OD(~fpgW<&`zZEJw)6Mx$DPCD?YtyFW?Gl&xd={j{dOlrJeJb>t_< zwdsip;UTOjrMST{_Qn%xtE7UntYg2s$egplSR-EXgA=1g!mlk$2#i>{;$JVUh;f?M zoQRQ%dCY!UW$J@ie0uf-%vku&)KMm}v?$rFC{|0Y0JA_Yss{H}{8h}=H&J0YR);7J zv98ODYaYDkv7br#K8~j{k2e@5Dlx@WlLrq>VmwPCY}fkQgCsc|fZqZ$%lzY$81TBb zn3pRNIyC*vvFDWoLF?qJo({H1mT~^tr(NTlR^#i+nH+G8Lz*`IH)ChWaq@xKC8!ez z0s`;NbTX=GFZlLI6pPZq2Ak`i2*w`>K5GN|efROh%T+OI-Q=y6r%pboCkReB>_diYuTa`y9_q37_6xx||cv?GJfA zDWiz*tG9?OEfRsWh6`KJ?)sSW6+$;B{~10#$4oiNNF$V@fJpxS7h*>Rke9be6( z(mKU+M~d$Q&Ur+f{O%*Jm&Utw*<-)H%Gn(36%ZFWyGgP#a9`lF*~;FE7E%4LLwU;+ zfvTErN~n8O2v}F>;7>^Kcz>Fk8(co`e{+Hwk2@_SP$y9>8_HJk66G5t1iFFNFQ$+m zhbfGQwP%o$`r$|{U|B^;;TRDKVQob5tqj{*yZO3vbUV#nx%fz{Wx+jh`G6WK72yGf z6nRvoQ<{8bT6FsLPc;w=d*%7IujTdZ>3Y*bm&7Q*OL6p-c;8kr9`sfKArf$hgl|fe zD1NwXj@;gruRv2=LecCy9qG2sM#+TEF0hKu7t%>^N0tq&Uds#USW1lKP)y$ZN;qx( zJX*MaeD_7d{XZOmm%+q7g+U2!R$r*ny6;Dup!xCAjSn=1s=O!Au!++(p)e$AHBCx3 zm6|HP%qO@pfft_*t%|-*<0XtIHv0scoRO~qI@sLtSai0&2fGG46eAgP``sZ`cDr%i znJu;+Zh8`H&f;0&&z~d>c|E3m9~TRxSbfFd)2~;-V;W1Rs|Snau^n=a=IIea$L+}_ zH+|L!=|(~!zIJyyc^$juC8gb+GqJGwYrXYiqfx|>bx@|cA4q1lgF3z`M7r-g@jfRs z6ajwFHWv-k@Gxl5RtXCYC#{~mV`~T_{mNHMC2Ho1HcC3>Id#x`vyT+3)ZE+VPUX;i zOV*3#EA$l%9p;MZry8K=%vZpsc~=*kK3jIWNqV(bC`n<-8YU}mYx(8&9bwvQ-lDq9 z?=96zlh^X5F0qp@Xwxp&B9WL^H$_udiY+C+9j7>bdpfI^d-+5f8^?woW>k#$xdv%F z4ba_CHNKGGd3lG&|3jP4Op1@e*813v!#PBxp^Gw>CyWON1{cPvhRY6_V4Umq0BF?- zh~x+gb5yxOlw`+!v)elr(xbHQ-I(`Uk%mrGqlejxV(}vq82TT0$o^`!E7#bdtE?jb zj8G5_-!KBfBZz0cR6B{mpQ9g;s@uE3W2@1PuW{N3KuFqD*;dHEz6HrUFp0XTt!)L7 z=ZNlgKHNo}EPu$B+(NCH_=E}2)E<@j{)!a>r0G#O&ch-Zp{)9N_&BDcH7|jDj!U9A z*UtNG3Wm_!9%+3C%rjYJ<1%3Mds+ew1*c`>#4ea*lEw*)t%k4H>@M<&NU7g(ae!1cQ zrmoN!yj0{C24k8!^OKNn{T5UlE0*1=x3;Y*(NVbvd3p*ho_JWI_|YV%$pQdiZ77ru4>M*ijrTw;-&mu!1r6Y>t2zJlsxeuo||LV$Zmio;80o z#!~a8i-U4kU$E#xUkE0ZHiw?ZL0otd@2f~ZC8$iGn>jGU)Z1BXXe`o|yVT6hw4Dg4 z_n^(mEvj;?o7EP@(RD^8Fh15cUNIXc3aMf5p;R8KD01rtgX*hQ4T=c!-OI)cnde($ zpXr+d`9IRMJdWT?JAeqT5yJx?@8U@^gWy)6t-8Ry|7l5Z*5nx`3-JDq>*4llll|QM z(;5T9`joxS+42%DeeX!L%njq7yP$KuCuXfdVtTa@k#AEuaU7Az4M{r=A0LHRaC;Or zBCA+SDorznbj(_q^b;ays;y4WVL9rto>ost^jNJBJn*}5BL3D(U7`M z%}G`2N)E5L6ZT5drvjxRwR~SuQ}2RjQ>BiA3<*W6qlFDl#4p^SRWDK&U-|1r-No6HY!`x;B(l(pChh@uK3Nm}}KNEp;ejyxinWz0+ zNW_x9Jm=RT#NiW-g`i7yN3U&Lt1Ii!Nkt(8VH zwffD=-{=Z@oK)ClyBuHzvef})5Cvw}$?w(M3zH5M$iL@yqLr(&S}SM`G=1zcO4VjJ zGzQs@^V4W9Ood`wY+*qdp5ffqp^%SZWC98qAB$m9zR9=I-w2ihPWJ0t1IlC%1(e^? z?fCJ_>3Cg;P}#rq+)+aFKmV|B3qygCA@Jd{t{gyWju1||*%5jy5qprA2M1KXlIAClAFeSMT{x+tbtx&WPT$y}Sd`3+{$o_y{V?IXd4tIF@?&H}DQXoPS|g`vzw?sLS&Oip68>+R zDGHZmdsKV&s#gpKyvFOe?{504T``I#!Ex4bkbeSC?t4$2d=@hf-a7K|uGiNx?_$3T z@2QT98%at>lcVF43V4~z)DFo&SeYdWt|6ll=GzPWuP(hEPm9TuG=7Rik|qm85z;bU zs>vSt;7X7)9AAzd6Tu`JR#lUYu70#t-)j4Zns2L8H}`Bvzem%%OcmpvpXolkB+_w! zVL38ry$JT+m0mWyd8CqPT4$9#P;8$S;<8+fc7uIz>x!1X)a}JKJ%r1@f=$1zB_m5z z?fx*`3qyT*vo*RlIGD2bLrJxRz#}UxXKB1MxdVh`qatq!S?ofTELJysl0M3cK5lM?5 z2}?O;!|vC}w(If~ho^J@j(KH?{+lpYG`OPVsyw2-@|ycvyJuA{%!Mb6#&VS$=KgZr z)xU$AyOMA@orf+hchYl;i3B=gcl1D!#l7MFO#!GRcgg@JyU@z0=5sOq);4Y?2Z(Ow z&n8ZkL_F4iuM1gRFUNo+sDGoz*+1PtJ(^2WYcikT?ACg6K7m}>#@QRCP>a>mERvse0TaWA z0{O#{(sq)i1Q3#tAPYOB*0$uQo5a!s8`>IZ=T=MqLf`9X(slT}_pE;xRQY^VByr1l zL^)x$&cjR{wsS8o+i>(X%B2;__zENe_C%J$aoUVs#2wiFxo8umbyJiD-ba;u}7rq`+&HU9_nv`{~&~$l|Ut1ff5gHw{lAtC-R0!qLTAB zw>CNqe0-I^0Ma5GoN=oYE9pSpn|6@zQTUi)xUMU+)>&w4pp|SxD zRw~oeDX(nn6s`tiWx~XF2k~Ply=Bo_bvLbW9KDxTUOinAJe_ar8b;QWQT;$Y`6Kcz z3&%%=BGLH`#8PM7>vb2}<>S;F^pwcM8P?%y+5L8E`)%52!6*rV2q;xP4Fu^0O>c3J z>#T?$vQc9}*j$vwOaSm^D$C=^+#b*+cET0iC>knH8J@DULy$vl^%-FcWk*nUhd&9wE?R`li%L2Ndu3Ll76f^UfF?LMP?L!f{ zd#>N+Ya}$+>#@)0?bvDdZ=ZPQ(6K-HeHyX1r+p8KJ{lWRR2%zV8PD_Q#N{* z($;CuW3BTiE(Z0LJ;v)&4^JbUjnq8X9PjO#ue7yT&4Jf$@c7=+>{Aio>3*Diy)+Wc z7@Al2j1-rv^|=C4HjSNH7}swHqC`Q4Pc~A7i{RQV98Gq{63|m6`jggM`DXm$z>;Us zQg)Ih;T(k|dL-SNg+^d}v^f)Fp3nyI4)88Uu2W_{EGSark%~IFIrK6Zsr(X_KH$up zp>A;?sn}i2iFn!?R(<@2MFAb2Tn^q9!6eI#k)pW7Vy23mGL1WpG+TUVk{eNnP%irB z%ohKCJ@22-uuAt0v76E0e$?dosDVw0gZ*oyLMltTc1bq)6DHb_IRJXTO^Q9)E)eMX zR{(Z!icQ)_<5HDHbbsV+T)(dw&H4P9h>SvI!L?V2U#VO;(L@SKlxJi9L$C2uN9zH5 z!5Zz2k1WY1uXTtDA+jFQuxeYKvxs`<91vjR2i>n|H#eD88POOa=#JziZLLs`RoeWg z75gXNl3;OtIE&6WIa$!uF@(9x6Lto!>D~dv8lIz#IPV|q`RL<#x;uG#Kh9HjY$$IV zt+?9j|CFAQI>d8omOdhAez5WNGr=*gAlp?-cy=$MN~o&6&ZdKb9x0s=uSY#c#>to2 z2mzBM)8xvDxac>!CXzq2A$b(GU-o8SaPw+){8S*8ngoY?c}KV0Lvmd4aXLyWTf7ES zD#Y~s{kh58MZ(HHz%xnf)TPLxwd~59^og!2eM#^Ml=%k)+9dsR91LShG#Z@G=KUai zLHn4Zoa1z1MwMs-wJTl=6aITEOB1eCn~6_476*lU1hr0IN?q~iEsa+j1`{S)=vt

tvCWX_&*y<_IZ}!Ui#qpp*R|ss@X-uQ6$P-r)Qfp!Fs!pGPtPn zLSpPRscIGgOm3=50q+Fb#_bzbe(|ZTdXv+iG_O>ijzN@3@M@0hGggzrQ1XBga%E*<^vxWxWuXWJ2|zVF57PS;E`s{1*jJ-N;; zAwf-Ph$_ZKAg6nnQL3?8NO{qxHiI6aF(?!TVQmZhfEIbf{O>8|cfk}!rCZgQ+})VG zm^nx%hysDuf06e`E=zIH%Ov!M{Ngm231SHTVmeK_j*%NAaPDjF%L2_5$9XYIp@IV^ zi}`_n3G;N~PxZgNKKs^K8=Qq>P@LGxX9|{cwNp{9gZ|wt@b0JMZ}sQ?Jd7tTCUy_kA0|F!%B0OKib}nxAdX<<7k?12 z%(o`;bVRUu8CN9TkCRSyU=G}V{jsy{=)G|H!jZh9?B>r*?mtrK6VTZg4&>QG2aKe` zrq@s0DF&;mF!~>XDB4tL`3yy0398Dch0Vq)Tq(p9b<02H=Z8%3`~yQrzn;pAqqNc@ zYZHM7ze1h}DLUKR%^U(Bq0u#%StG?YZRT;bc1l?YDh{kddRxB-tS40kMioM4=AMtF z;YIsMy^zXa;}xdHp1WTuHOcPYPbtuv^#+uCISaWU2WC-J{^IddGQg0s6Cmhz3p(gM zKUDlAH=NJ*OUXb$+}Zxb0ff(mI)+=kD(du!De747X*JrX;$|`Xvm+Ibj#@Pu5en;Q z^pzv*>}<=Ah!2T)DB)}Fz@i)mOl`AA057DdQISwk503;<$AcRy=4n7@C0Dr+#Qr9h zZhhvJ*cPcyNoq#@GgEm^aDeS;-;g~ZTG;`ofExWd0FAjFq=SP&JBeye2U{?64xvB; z7Tne01mQ`{lIc6yE%0_hHvL{lFf(dggj$IZD7E^6SNVSVM~sI4$>bJjb_^Y`=?q-m z_la?SN^Q!kUzs2Kmyw&=jCt$(xLq;vN{##r2_V@p)5 z$v+9`9^9VnJ%;7@E@QBWmapVUPP4Dh1^v)Boj=PONQHjFo(|a0EuKZDA9kyva#sup z5Rg)}X*O4*5}*#kJ90MY?#X8#YP%87bVGsb(rlE5Cg!uUET!_(DLne|bAVHO9IUdmJ?mRb3LY#^-(8n6vjN(^`mI zed>BV2RH!PmWH+Gh1oXxd!F}wGJxrvpG*Sl_APsP4SG~yn4j`i{au`OBZeffD2~{T zq3gMqXC>(=(fuy*be6K*;ArynecT#7N4UWOWbQz(Q>hl`tY{xhPqsf!u6E7fh7Q4& zg}Y)3yV~b`n>V!E75JW;z@QC%$pKycj+*lI006O_)8>+Fro3Cq30DF0RDM=U8)+vaF)y>ZVzl7ECmAN0Xeu%if1 z>yH7P4*y(N0q$2gT)cXaY1*oL{_Be@+n{h6^OqYgQ~@=ws2@Dy-gP}ULL>mPT0Gs# zqNImB$r8bxz;Ds5(*-ph^6oLt7d?i#%o7>yvc8!bHtC^xi;Bn*&HORSk&12ewETW5 zc(|)R=jSh;eW$c54ahifd)=@JsT%0bJ&{AF!b6J~n1^XRczFBjF7Juz(0j0@?~`pB zoV4%A(zeN)L)$(+6A)zdYVXpi5wdzOQ5`J$tehRB*o(ccRb^X5>pGCI@I(2VWE1iE zWV~R-!PhUis{CBxI4@0lESyvZv=)uBDoFt2=BY!KYNFTP4yO=c`zV5e%Ydx1j4+AM zCyQpoXSd%B*upFk6aRTLDrD;;N}U6SQ?_4HzWE@sdvuWRBSq7V!N-UDc=}@7{ixM( zGA5o7s-!R8{8n+CtgFdJjGw?*4 zW!Vir_2jG7H)K&%`2Ga{@l?*KvGwvFe8PIkJ zS)W*e@uzsV$QONUXL~t_Pg%Ao$Q9k2vskK*8Q%qSFa3JSa&jV7;L}0Mw{9F zG6tb%?7Vmfbh#TJ0H#Y${GnZ%C`-W_vEO>!Q^+hgWz3L2s==tRj-z#r&!;8?9ldv? zRmCp5D2y8ct727rEd!aLY zk|?abs*)dy?jdBm7nuLl|7BHeyD#T&cL2X@YfiM`d$dBEP(r_N&Ax?L;#45JX+h*t zqRiK*Nz>4%+^(4fteJW!H|@z^rhpz2<+1m%oqSYu#^2LnIiEP}fLiZ>^Z;jU4lStm zM(vc(Nl1ZkPj48|kQ%`LL=(2P|KdiHrZpX9hOc5}p>d;M)zAHSs5YC|T(?Y1rQarE zCKVDgvc8S8%{V_$`I^%0txHGJRf=} zHh%iMznx56L6gjI^A2@}y-?Em%csIXfQFvtoh$7hj|4LtQ=3Jg#zFB|0W#Xv3IyHc3C$~aUJH#QoVCFbsv}UH|(TnT0x}aV(>6C(Us&8OoMwC*Z_R`cj zPV&BA551AZ=Po9=R9WXf#Cc+!3*|#K@wwHuf)pI?n)Ahf6zcKK;bn%XtpzE+@uYNS zO+pY2p zN7rgN7F#?dwkAY91A@D2~?8VvBw5I=)I@kQ;dT(3ae9fgZ zn$lkW%aY0~gPG3o}<;s;sY9*-7hc5&ku5(=-i5pcJD05$Q?YuZhd9jh=W#>KkSV;q~b)lr5xij zdAqNLkZV6EI|{U?iO!;&i*%g?$&MY%ynx~k;~LK-dmUf<-7Ik}J55O7gbt4N0dL;d z#`QL$^jj*jhclB}5^WT!beAQ+U<0#dlBv7o@5)(6x9l|qvN|=OrZDkxdq0A;Hc6J3 z)4Y}_j4pDHuin;+w+tU?(yf}tGbmLcWvnD3B)(K6#f~aUl`9X&;lyJ$U8K)PCYrG` zj7wIT`zT1|^0|_`FYd72WZ~~}&Ddq!CHj-mHTkw8C$mT0qIs6KfhCeI36K%$g+8dr zSj-6-q$T3;G|imoVtWw^|2mEFif`X?v-nVIG7sv&3ucDDby3UlW(8Li&D9Ko?(pdm zmMHQsBZ(&BI|5A!lxEI}Aesd$k!~Q8Iy=E)p1`YLt+@jgZVX8N=a;=-Y`?udPW6@Xk*4Zi)N^&HP z@s@+%=1#o&$EZ|w1Q{RbO#K2iuUBwpC_=d~h2EaUwD|KmGQ zZx&`^D5Vk?E5Jy2jLjM^{C@Ci*WJT(A1OO>MHY>PE15SismS8haOJ+&zXf^e*^1(S zAQ8#621yI?NQr4diF+szhpRx!k6)YY+&)vcHSHTb47)@dcD|W>LxQv07f%q^t^b)z;u^i|| zdPy1hw0WM==5_q=K-75(amx;9G<4eD6v1=;vK!jx=k^6fc^g8?N2DMzmHNl!9Uu^&8vW|?0!Abm)QUQtZ^Hh z+$n~16rxwn^V_}Gx+9@@n>r9q>m<&^ukK=K zU(yw*AKmFL`x;75A*T_b08gE1ZTFmnwbF9@=9F{`afmP2^>ED@Us%4&H*Q(2;4J9t zDvA*tshYmjXVz_Jl!~vnM!cWZEqHCWweJZJ%6C&JX*;AwHhIFN!WtihEY7_L9@8|P z*QNc)xd!hVV3HlvMQ>Zu_N+XAo5CEhC|TF`#XMy%O$@$tJuoPL!jaJbWRDExz4fVr z(o|h0^=_!|7zg`bp-{JKg@kvfUZMOZZq5Ok8>V;G5!}9IPYKujAb|z=$wiJ7^x%B z*aQ2U#WH^-;VR2|!LD@=@0Q%A`k^nkK(8|7HMN&UzM}e%d4PcLT=BOI6bp zRWRFGFb;u_hr;~T4{!P6Nw?j4O;`hKL}JyaGvHv{WMhK)8zrHQn*4MvHi172B&je^ zDDN9_ulev-~Hih2E!FU@(dIOP;`P2fD|w}Gfp~gWb7Y< zQ^e=QiHV@UB>|}F@+gBv!D%%y(1--s1IlRC7&+IN>2;BH^9w3RZ+qj`Vzz97I(9ZzOp8g~}=7OKV zt4A45J5Yw~J@13XTFX)TRMDr$Vg=kX1P%Y4EO z0c<_*V!Zf-`{K`+YxIZpDrFLlvj!f^z^De6Dxmto&7Z9=`^M)T`$~KN2dj)s7w7QU zBW>s?SAu4OsmYwoVs$Z6_(;u3awfq>9;^8uwT-$1(K--qn@I71Ng;69$iQ2^{k?B~ z{pQ==IvlN_B!G%8kms=-dP;Cgxecp?07B~Or0H)VP^d7`Yl+aC^sAHa-z-$p_X5Be zv?{X*0b=y~UAQ8DX5UwTx%AYh9`SODCExMB#KAMK`)G}+MTQuyiN1aerJC0!?t3!s zANnt*@F4)y>@fBn47r0Lx)`F10rm6qUyNTk?O}NNg2$Evhmo6}o=bh3tmHCmFpI1x% z<{dT7#KcZMBJj3J2pCe$CyQ!g9m^yR(DZQZv2MEXD=)k91Aj5o-+ktZ*%PVPN7n5I zhOTO1c0s014lt347-$+VCzPL~|DJ>Zu?LfD+=T5aL=-RxZ9J;zf6P08{(fVb)fG?y zMW+Dw3XHh^?GK)?`$_;uoGu)NfJ-U61j)ybR!o{k@4ZBfjAjw*PxBU{B4CIRFd2@T zUTm@-0Y=RZBj3RQg&ZBs&uqq5FS_`CTTaCT?idB8t|@t+dcV3%>2d z$h2rliym8FI(?be2iz%8&@Jq(9hHk%0l+oW`@-x41;gKvW zdoPX0E(iq8$4Htz{YGp4vx)53wCV&1rhQLsp9S4zsN@VoR>tpQ1wCAQ_5<*5zx?a? z;aTUqy+dHR7PH=(`$qGRB@t+)1`dvZl_5&rgE!!PcsUN@4x}yFwYT6gHT{+Dz5qA` z^Plk?Ja@-#{Q6=ATG5nVHq35({W$3e1G!uQ)xy#b>Q7(x5md`VREtB553XcfS8x5qNMl4xnHsN6{~Ol)HES#nYaCMBRlGGYjL(eWoNW>jE^BrD6&->AH}7 z$_Ad%ETay2{sHM{IE;{Ezy$^z7=Nz26(4%q3-E8x`&sPiY{u=wfKk;(snz1&kCB8z z<%8B=8UfWZZoxP3`}h>z1s|E-HWnQMD33Ms19#U2Sk3%;%%1e)c=U+wH;z~mz|H-53MKo9E(WV#k)*mfpaAjtg zib%8hDMJf+0{#=LB7FigV?vQ}0W`Ca6?|5&fq@zsO73999gIc$fAhSD;*(Fj2>W`Q zF*lHqw5&8XkF^37UK)7w9p@mahH%a}(H{k?_>o=%BOGQzDya%c>_`cCJ34=_M4N2tW&N*a~b*jBm zSXB<6TsfV`(C0Oo_sO;ARhW-r6}n#3;&Tp=G7ETis5r+MImRe3LV-QoPQizs@Elxs z#`%~lft7)2)|r+@BriEDKmh#e5Qz+bsp5W2K&&ok|X?g0!cpk7$M(tqXh%TX;jl=F=8;0WdX7}Ziq z@IK1@H5LvTW`urk!^cQrtOoOw*+5+T;6)G+QS&f|$~l(QSf>#Qn9V2;Z@F0^u$CpT zZo2UQclp&{IAzn!?)#s1^7Eaf3w!neSMa>LVSEGxp&C5xeCydmx(FDJudI=@Ejb;+ zpekcB5E)@$=CZLTqh1RDxCW{bIwAxZ{)Mmj$!GuYx8L`HOV=AHZnz>z=%&W3035^n z(Df(%R+c|0LXv1$*n zS`7FS;0iSk;6wNVF2OPuu{t88t;Fw9&98Ll1we}P_mI&3X!@V^9Q^F;EY4r9g74E{ zK*OBu%sh!?9@W5@!S&@=y&dKJ3d(~y$~i`PaExlH1lO!Se_GS2I0gdxMHE;yT`a)n zxF!>K*=)IZn-g)Dlr>J|QwJUMZ^8jmH=je0f`WwA%&*To>wWkyKmUzO{^IG6*?rm$ z_lSP4hpbyj6OmfnASWA*2&0I_66yzh^m@s~-ZzctMv`L2SBr-x00phCR)BU_PFa=q zr>dYJu&?3jF^WzBKhwo&C+zsG-+aPjZ+p$>zIfGI!xT%N9f$s^PSNx<=Q^j2x#!r` zd^PYJ-G{LFN_MD_qePAp1y)=SU%240_{1ZhiaUx;I5-XcA1O0*G8}Au{(F@9fjcVzQVo9>P3E5kFf)4r&e?GqE-roW<8^?v)2Vd} z)#Os^-3vlmt&G0que{<~j1S}(ALw8_2UN>dGOBcerC4?pDr6Tx0_|ienYK}(`9(nQ zWAiNlx@a^kChG;kr}kp+2mji1$%%$U@{^B%R0ynKeRp8Z`5D*V|K(@D{@Ry4^}?4q zN4xt)5vm7=BcN7aS;t%ad-eKVGWUb@)%RtxV%u;TTN#h0AP8fZwpU{~aohbC0>tIe&E3-o5|z6W4zKK;wt1z;TjgnMJ=3(a>^97$m_EPEt{4 zJvzlb7(mS#Y6PucqJt5-_{zDDz{el?6S!s5E*vbwkWR*pIQ=NFk(s_0#vkJVZpK^j z6?`5(b_=%5uYWbwx7rBi2kyKDpnm^ktbYbT@8k>d?;N4CDB9oaEE(w;_ovV`CFhiN z2$T5R4txZo11lKcQDA()qgrwk=|PgDVSPK*^k{VKO`6TNcS^C{sK~TxaAFRUQ;=K& zHrs|BnYDjN(#XJC7C_v4VyzGET^Jiw1e;5zvI@dqkc zM#1EVqhvX$>tg{B)tsW`A!Wfa)xdGYI#{d#R^cHM*}75@pCt9`J-jdBKIR7yZ z^&N_iTmS^^ujRbz`$y*QKM?2kw%}1iFPVGBSF+HQDoLxkNs)gh&)>S{ix}TN#AqL* zS|q?X{o!c;Yk3c+Yfgl9l!CHK+9PN>wb+yCt~08;>x9XlD8rQ%NMyo~4J+VIlco!= zCji!s41DdDeS6=3^$%Ws@q^C$@2_U%|MyGZ{@(vJs_UdOVrs9X zC?heW0(k5bd{30D02^guG4*RE)W}eAjv;mNwR0YhPd?;nxM}N2Sge4-C^2}QKAsYJ zrn$#F?Qd&XWxxCo&M+eA@+n< zF-CKzptZDqNblWX<_C`40#JWcwZ9%c03GyEbhhGAl@BO>=?x#LVx1UF#Rq{<{#$wg z-tWW0^#iQjz^Dgnx0KSDzUc~M8*WYdM$iVUoqF8o(t{`N;-zNvrac_+H3&h&aAUDz|YuElKEY`BEH2Cc7HfDQd| z)Y4JQLyNRjcqHH!nm!N(38J7$?t!BD1|QHuCaytsiB6|LuiwMDr=9fd|LbXwyWwv? z{)Nx75j?S=C+06C%Pd(6h*p3H!TV6-SHYn~hC6yY@P+dqhcBJ?XdLLwVyOhmfu!%s zZ*;ZPS=e2Y)8t0Rf51)O!{e{`0yfPpA9zLg*Kd~jQ>{PA{I;flLrwlkI=lc#rM;^C zE%SE)xX%4>o^#k#O1fjk$+EVJrf~-f`NqCa?Pdv7!d`BSO>B2 zh!QTq6~GQf(Ls$K9&`WmUUK99xmy9QE%R#&^e{I*L@_k|PQ#KQRB&JpOkW|x_ja9) z%g%c&uGsxxEOLgW8Yssh!I3i&a59cQH<}(%rT`vrCF3DCU5BS$^;Mj(|8@+kF$UE0 zNZFi&bq>|~8*cJX(veyKIa04P+xsj70CytJ^9am8_6e`oar9(dcm4gQJ5$QMb0?s@ ztqSp;wTTdRaPa|4iZd1cdHH5GAt8+!uj>9Pp&<6jqzxaTreAv)w9l5!roVTICPBd? zjtnf9RrRXNuKcV2@x({`DP>zu>~}hF>`{+W!Jz_hYWA?nUIe93R?7NI??pIIw0jI2 z0?{(y$mECsW7?|`!o+cqrPjcO_k9V+gl@M3Pw2e(i5LF%7q0%nKiV3Fz~Gv3n8JSS z0QL@^f~oJ3V=?dJ8@nHlFP-~n+_dEsELFhDIB5H*1oEKq?OOD?tVih!!XC)SH6HQ9 zYw+anUXByz=S2KeC@=;w*9d96R`cs&JNaw~%6~XI5&@v*r|o*$g)vFFhZ8Gd{4tw= zopHPMdHkCpS_4(YyWLKD{;!|HZ~ndI^=@X;&$kaJ!+C&@y*c80D%mLsjz$;>NwK9b z1yUO0T0h5tQxhM(3v`zw1J}(hF1+a*-+jePe(e4)%iN}3w_6|s!;i~wPfk%zP7JGI zOB2Qekdl84_?fEy)Xyh#J&MfD6UVCXVLUH2X(eLR0t)tLy6DdIw?FH#k9Y}X1g;dg zl<(1!Iwn*gcy_2cL&X`c-+m4*KkHGr^0WtIo(e400nyiK)UC$U@?>XztIlT)a0$!| zhj{e&zlFzNcLlbrtjHE)9yuxykC0;kk8urP9*N;?7oV^{;Blt)Egf0_B=g_)JlDSG z5t*(WX2%?WzgjvdH8lN%Hc9qYcyUjqK9!i|2t`Kp*3WI}@0 ztkp15yrf#R@M5W?SW?V(LiiSq~W*z2yqBW}0`-Ek>x={-7Jqd*xnKZdAy84Rir1i%o@-GPs38Sl}eBe4K7 zq>T<#0OV##z}Kis4cw@HnryXZ5mXfd^6j2OFF@}AKH-b`a%DheEH z-|d=Bj$C7-OimY2AwV&lXo^`#Kk1t|fPjkXSNjQ;KZze=$Wm|4}MgNCM3lS_3?$WbE|xpA|m&?j7f9WYQpDXUKS=!gLe z3a;l0tQ#5lv(H^|>8qaEJAHSaJ*MC9Bcm=b8i9SC#@|#uhGwUU@ip;Bg@F^Mw$*qk zLy!#PQ|MGo1ddpP{2-!ebtudlEdWjCVT5~>#+x-~sM(?B90Tg(nv))gt4?|tuHAKC zEN}-)bqL|btn(!6|8?1@PW?d_WZM(dv>1jfK%CFI=HmO9D z_pPQw^On+sb)yD%i5NkvxI-Lk&SA~WfA*PgzV0ucdEv<}%g*j~3pg<9@d)gFO4^HB zTA5jVZM%6ONtvyN?hN=xPSJm5d~pLbc8??oVuWFG+@Mhkjyw8QK0}QRD{cng-Sr?` zbJBxx&CdH{5k=T6bJR=@pN!d0Dwt@I)&SLvb8o*1kGSzF-1pWSko!7r6PCfFg9;t8 z8oxx3OY~8q%fSL*3^C*(GOj&B5zkSZ^m~$y6a<_MM>XktxT?Mn#@?aGoTNrt-+w&^ z**C9PacB=dF0y|8^MCQ@xbZu`hi`v!#eRhBqX_8fV~$^_QGrIgD!GZM%_DvwVnUub zFaWSA@RsjmO4();h#|@QN0BTjIJxnp_M~4E6uf<9IQp9}e(ROL^Q4FUnakYPZYKx< z9*^W+MG)EyKM3F!nLoK#-k9+T)Kl%RjPH{rAUOsRYmv`}yo@wP%mmK_&lzgYaj@8q z@9umMt~v3c`2P0uvBY`M^rdvtWus&!txa79UPh%($Bw0WJb2Hwc*xDyV(an}2x-s6 z95p&rqu>e!Re{kdX#F0K(Pgm!1OuorhG*I7Z%UaTI5G=B|Ee`$4fsI&v4{nHZM*}I z?Ko**UQc||S^@fLUAF44aroG54h%QVoIL(-m;NdK>KFb3UweN85Qxob)Wq|q8HZtP zy|!*-X}>!N0WaX62#vU~Sm0svGbh2!#voBzl?~x>)MzqYcv2Xwn=bs#+Ya3Ejw`HL%zg8(IRyx=K;?i<9bmX^>uH1E{nwY_oiG0zzT{7@ z4tL<9jhz6yz<@*~v3=P#EBcw~?lt*kJ+gZY@PrAY#YTV$g=wTgON5#3MlR4H=}002 zYf7H?Tz$i}XYAPYPfxhd8UK-HXVB?(gYc`h6`}R3)c5BY8Gs`6AW6%$E`ve;V`pJV z5l<2XI-Z^bdcTlw!}Z%9fFJC55Wc_t{@CByisd@A*D6O%pI);DwObR_roz;k_(0g6 ztgLX({+n>W+rE!;?zkCwRmYOx(B?Y;dmZud3uSU12Qz=-C^(##v5(!~n||N)(%}Sv z{#5HlO?vc!uEPyD7auQAz%%k3@EM>MQlv@yA)1tk)u|4WPvC(~IndwS-@f$ofBZkj z4|(c)@V{RCp7=pgJ;Yk-ig?lHR#=(`cqb={0fHBQH+|lPR~vf|Km`sH+_4h?z}nq~ zZIaOX`wo8LJD)mv%gpZcPd)J>nwddX^iYpi0AI&62SB453ituKBeCvOOa{@9-|9Fb z{c+P0u@*cLJaP=&ENsFA=+q>r&BG7WqwFH?Q~R z5zYI&s&M9kJ-A@s4{*-@n^2Uc7%~)Lo1E&z_*|i&5QSv0008hgyp5lQ`_(fzqmuz;^rz8G{?{myJSHc7C@HNg z-4J9Z15W6R&-u6y)%zVQ0R`|iIQn!00eLQQyT_yN}M;AS==FnNVlKPk1A zO7A(1Dwxc}xY+dXv7xmS;E#WFe=)WFCC)iC`a)6u+v z&+sJkYlMk|a_LkR&YZg$=ihNX&OUG>dS#W0JH;AwLwA%|cIbmz+mr*FcWyoHjTik_d}+_s__?qAEADswHxWxf_1Xf^CDYZk z`U2t&1Rix*PhFEtGE-vohicxphhq~O9bsRhLixW`H7ox zJHCQHs~&~lcYSQ1$wH$~KOr%ty<4m!0R$6NMy8~@D}){cT?cH=fm_eIA6|C)|HSFH zT!&|0{yseJ`{fzu*d8UqxmQh<-J}_yiJ1k0g_bq6uQw z#(I&hDWgLRfJ+Ium{kC1owH^{y zBqAJ%Jr@)snSP=Q1~N30@MtCi9D)uP8CW-6_;c6aw&#qUn_v5!hn@R7l+U=l+Xaz_ zug8G_mFdZ0nDue{)^l+C)^l*n_6u;^mUD3H>{%Ef$524Kii1gSYatjgCBHGnpefvy zdA#_TVrzD)5~m-$6=xr~31`jSjID!(iK$5fKp9?-oa^B0bBzvpbhtu6br1qRg!uI6 zaE%UpNNgd+lf+kzU7*d(vn)j09%#zxNHGAdb=G=kEe2YD8;qN9JLd6+<0s;m>m7K) zYzI`h;Q!T}+(;lbZ;U(MA}y5YYbe-{AOyxN9ZDRKZ`q8m{n)c{*(0BgE%UeI5#PHE z55NA)c)%@JqFWBaXES3BAmId)uEF6+^o|H7A2k6920(B}ezChtHeGnFOu=;{18@1- zb>BF3$L!l4e$J`?t~Waa-`$J@`6le$d^+}RKL`7^oQYevo{IxBCu6`lMjjZ*E;sck z<#;)k@^76#1a0m!!~ASuRQ2V>xnvJe&DgcPA7{?(!I^V6ocw`P&+gv1BO5GiKcjzO(nuEXbyAXKfM3su<+bD)TZaoc{oo#)aqwpBp1%dNqaji>#l>G2 zrb@Qvj+(x1Fn&&f;d6=6=Tf+n!=pnUIXrS=59Ii7Of z2XG_;Ah`kB;IM;K6L3h-2{KUlGQPy$#kW=-hZl`^;c2rS zE#D!#2kDngn13lX0J^Ab_D(zJ z++ycRXLYviIxXLJ!b#bd9VgN3){{{5w^b~=)-v#AZQxP{Ns=*8DJH{7i|fueVQcb~ z_vE#dwoda<197`O7RY$p;2=(0+=J5>_TcpSTd-xc6k~cMVxOXeg;b2ACO&Fm{B(rp zl`wr^_#7%27&&u5@fjvO>(b5Z^hOIH6hsA#!9EsnRIb6%TA212z>y~cSxuvbK{o!} zKkT&*Vi_OA8>=($q4|g6;*}kE{N@hwz6gTS3qS;;MKw==Q-NXhA$4LkdO#_Z2q11P zK9auej)06Z?AdiTZa?8{eDi_Ni05`kD>!lPChR0`-yk9`Jc^h^Dm?ei(b6}SvoW#J%OgP>Bmm5y@ z%qQ2(r+adzc!aWS#a#xnMHMr^!-TYJwk%jmWI3Ft)>Q@B;6lz-_sk}TuyDLb((tbK zIALWUPF>uCQ2LiaK-<9^1M~EaPk+E0zWv~5eu|Sv z=|zTR49pVH;owRE;qeX!%rMaNzzNLg0NBaEW(Ib6#uf%T%)zSmoQ_%sO53Wb#@4W! zmpFC}X=N?vXPmM%iBob%jK6bg?WRH?3K1UwJCcgZmYre#JBM#jOf&)GLj`WzKHs`=ID7r);LEE{=9ocVpL=oh81NpWs=`7!0+_$>gipQi@f*OqM}_X3 zs%mZt7Iy=ZzcbJ#q3fW}Ytm-)+{5vh>=Zn)n8o?C8C)TsR$*XWcE{=JCVO4A=Lk%n!K1?*nZF~NUUTp>5daxH9CGNF^jtoTAi$n;#p^p?wN7=dCmWqjX+x%BVhh>f7BDQ$K`2FtKc1fc;-tb08j z1Z8^V3tN+=eHv`977f3tu&rwm0-iBDTExiK16qyjHmAeJC^Qy;{t|@^@rAc{SAVx73sj-Gomh6~9!%=R|3Cp9#hT~I?1KzdWfs+tW3qYBFGFz~R)I#jY1pxru zc5s1jzWGY_<<+Ci(dfL>Pgpu{_h~1cy7hsBUE6nzW@gZF0qxJ#)JD?snQA*}`>Y`; z=|mML*J|2`Y$KWAYsq)ba3iy$m@=8-4YejZDPx+o;*t7oVB)dTWLtH6FVR;=(&lRM zs3!NE(y;3q@SaN^j1OXIWex`x7O?-|JofJ2kDK?-VSZ_7zx&GEUvtg_R$g3e%6H~@ z2QEVt0y}Oj*V_uDRJydUEZ46zSG+>T|x4+jSaaMS*I+TH8Ad!}QeND=vW)W&&f)wYem{1wsd9(8En9J5 z`*s}MvJD5fZo}fHtytQ;6~mcL@I}!;`w1zR*=ljwaYN>6rfE# zyKds$4x2~~EEH6%xo$%W+_%R>`)}G zK-_siyBCpz_rB4>BKW>P$`*jqrNSx~b7+MeECCe&Lo@||wFaypIC86i(mp?NKYL-t zysB{G+#NV^?sh?keT?LCMi>=cEY57kN`DqBy;&^xXRy+n#kkYO^2{cT^9}~xKFYj6 z)yXj^`tVs05#Bj4IV}-s+-)*Np$Rj})2V}1jS)PS*`r2{C3pO zz(KAsq$MoyK^(*ihFHY#E~8CZuSRD}39cNtcEbE306gHwc|^uo8oRS+aOJPLwZ8V` znc>GCcIM!jy}UqHcyKiWxD3qfIAz!oqeF;{o*RbGpss?X{4fV?O(cRa%&9Ys?4#Bt zlbB;#!N+;mc)SP@5h^TLfJOsklPF<$Ncb~tFK=^$RQo%Iv@2u5jnst*ZD*OMTl)h? zLjWixYd~uUZ1IrYRAh300TBdTgoRmm!vb7;y(hEFnqqe9fMywxe4_T~4+fYSG+GR< zO73aA7atI+EJu~)vY{qL^D_cN3=F+TS$SO3d(ay{*?q=mu#C~FzTt-8&^r~K^cvwr*8CwDIFcM4?P8e9(n zuEgI*Wb}?B0sl;1g$V+N@F|5BB+!8 zJ&qPe#1kmF0V+shBp_VNODq6lLFlY796Wn?3+zlO9X$a6SZiQX5ZFBhiizhz2rzfy zM;`S`hI*v~KPccw9r)UToHKB<6rCsvtM)*c4BudX4e6w*lQSckPp?bFq4`8ng`iqA zJV3EEm}f#(*BI3v{c1SG7(?81WaWlE0>VMgBb#O9qYTwj0irIr>cJ0ss201ZmO7}1 z4qSS8Ie1*dk3IXbf5&IWZ~e`ScI?>PnYmBDU%=%Rd^HkRK$)J95y6pz1Hn-iS5?H zOt}MP4wShZeV-$Tu5F8mli23E%>=VHyJTY-2r-+cWqDs22MeALyYx*b^Z@@FNdDmSg1MM}Fi-{PvIh z@Na(Oc^CX)*4cbQuUmi};OjbQS7CahkYS-sLc&f;WO_7c!mo}q8KzY{AiU#1ah$C= zuI;;7dxOCy0C8Y`(fYB9iAjo(C^CME9LTkzg<&uRa*`_$dLkxO;lu93=C@2M9UB3l zq=Fz}1ZojzJwYe_^`kCE`#grXIE?mXs1`H$u>(+p@(ixyK)LH-N7bh;N{msVgf_A8 zvH;@tQN}h5av^CDrNpuZc8|2$F=#joBq>G4{A?a;5+CBV^|ZKUaLeR}X880t{mptc zI$HtC3sfsTjQ002ymbcS{e6`4ebg%=1jd|%z?i`$-@IH8-v8;rD_;DJhy8JpZ|QY9 zozMcT3gv%H4soNsI0ji7Hx&XJhmQBO_Ghw>v*a`qk$tuu9Ar%DS7~fG~@fybR z_cM&=a`-_9zREzZhATt>6mAn2)hs+p8lmD69&DPzYLbTb{!6>bCDv2v9zWF3O8Pv8 zoM0DdiaZ4^QpZJWE7$U{%bey(07u5;cb3`LI_g9Jr5eR{kF4)7KG4O=5BpfTaTeqK zv#1tl;fFKuWdW`!?9kklS6}${4L6*A;?}=?!lN$uEpi>|`DW-c~08CPH6Ka4;kQ;%rAt)b$@&Q~2%KUHz zZNjbwUCUKbw(Df*^)r^|5C4Nf8Le z-i@n&Pq1GINx$oQ30Z=g=Mkb8;mbWa_gK8lgi&S#(~Ics46trMiMf2`G%K-Xx5~wJup?iSg5ilC=;6644r{5eiv4Tw|xd zV;MmJ9FF-9Wd$5gK&-{&FnJd0TlRCt?!z55Pt=kkRHW&eX`i%#)QUVkhw7ayo)$P`i?_;>SWeQF!|M1WcDDJ zfqjj*nW=O)^`JHkcn=XvCI^En?vUpWh3@lCHe}_<@?p~kwE%SMZvfHh3w|I36in#7 zGJW_)tp`)nfs*zh0|t_dU5sjGWU_nANq(;i0J;A)ne@&az*-Cr+}(ZYJl5WKQ2(yG z@8JH0mEoJ-|Akll>Id;LZJ!)98RV6Dk{^PI)%q)CmBJ zQzQ$^f-$VFte2Ry;C^McuwP_oQ@WX8TYXJ^dwta~y#Xcl{7Gcr;yonQU+h^5nh8_R|5GRcqBc-qDZw`Y z(xT9=loZftCssj3g%unWVE_RF^*Y)EE}8u{3(Wl0c(Z?oepY{G6S7VLE=$yP9L>nw5rtOI3x_TS?*I-;j0|Ik zGWZP4S$toG0%GH;v1LVe;(MMD-}BKpbbxcKgn=@+ zc6~~(5xiIjN&AOmnrR9JfCBmw2}o>i8dAF08%`|)T|6PVqZ#!Irhlj*XX_qBi@?0E zdGFD6ptPvfY@JRQz>-D=CI!F%!Agy*QhQm9c)}OPNqMT)%J4D2=F=7 z64nc@03{8NU=gI^3L^x_wHUxXO{svyXn%DH6c{PZM=Q@Xdri^)tw;vK)Ed0a4blxF`a9%CxHS(=Nf5G}Rm6$bhj! z4?;+foN9368fZ8#hW8ZtcM0KVc}~tSKad)Lgiv5~Bc_vuB2C}jN6oLBZVYp-hA_c z4}A7>uNo{5##LDdP%!Jn?m<@L$D$z{$`h>}sy)@8x8q9&+zS*RQ*!B;DB?UCzmK^e z=I{nc^gMaq8ue2w zlT5-pu@EHYb;~~_sliOCUX;1f+atxHeM(71YAn*|RX@=>Og<$G*RQwV#=U`52u!95 z>#=US@LN9ikXBkq!E3M)o z9ewqE5fUaUpl%$?0?^{Z=D)J@3p-f@dM$?(8JcbzVCq(?-PWBABc=|snn{+{Cc#CG zPYrFarn>?2VlDtR%zH0ssEvb@&uFcIDIC@#9)1K+aMBf6#u20o|J8fn`LBEL*njzO zI0nNZ>l7d-yT)lUmSQSKTU+bOBeVhYUbk@5u~!$tiB{GGpp>>7AL}_JS)cM4lr%h> zC;-Q7L+hSsg3@$bd(*d4BlkD`eg*;)n{?2~?AFxuk`)-=%c2WlnH~tBU#)cn(fm{f zH_1R&c*Gimdo5WZU|oU3Mh2>?@_%>f+g`gczj)JVR01x8%L{~ViXu#nixq{g0I+c$ z$Ovg5`Q~hZy67snH5fmOzCDa!u;(;C8}I`k*FZBfahhrB1V9Swuqg;>nu`e=K%Uvt~Xzxw&V9;}S&ap^&M2b2{_2p9q2O~}+?y=X08#z5%ct2_3@lXM5C#Lz%9)Cf+iK|iDY z9<+=(n)@bSWZF%D>9YW!J^#WaD-gqIN@;IQ#28}YlmprSa-~<%pHC+H3j&*BT3hbQ+c+_Rq z_J<+@b_KhLy#f|`O|LVVlF3XmX_MZ2uY`{D-fIYyUT;Bd?Cc|X%+^0R~oafAvRqx$>cC2TY(~)0$u6ns_>cFit zvpb)7ar|u^4t{dLKL5q+SJaneb$I;oHACL54{sXy zX@2zE_!Ot^-QIjP;G2gIe;3jDrOkI$R`mug}Z36FXh|{?=YM9qWbkB;(-91!g?rpsf0 zXnc0Z=YQ{0`R=rO&v6^Ry7q~+2h0D;oG<^r9dH%vx2+r)+hgJkOPQ_n-RmaJ{{FTh z=Rf~S)1x|Z#hth}mz4UN8LpLYBt!>=`P)W6e5~?1{eqkBf9|>T^Y<0q{&vwD--TD# z48M2AiSB(*yF4`8V?nIXvDA4fS!ZARi!uKm>#Dm#7hV6+z=FZuJG|9+F!`ze-M+7j zXf9f`$mAZl{qN)Ub$ImAH*8(c{_V@NdHqwJoMyeUzvjcgeyn}Q>(*|I>%V+u_v4>- zdE)WLu$#uv2(fbSr(fLDx9Q`Wz4vXozT~|TA&(9EX#W#`e{yF`;&I>3kJ?hF@7?;q zhke54=4#H2xZ$>_$Nn04&y+2dMXp_MUgXii{-$$+cihJZ)}1~uTjO%uO{rZw-thND z<8O+%5L>_Kt2_Fm8usqP_gXw}cr$WU(X#!W zAHH7m?0pN*yj^z7{6U8v?0%<*^Gj~?SHJLJ`QK9->~Dql)$O$PdMD%Ct?4uSzo&cf z(?{>yIH@^eLi6uSzqr5O?(;L=+S9++#FG2#W_u;}NZkI6&VQjt!w1KT$Idzz@Lg0eIH{k}S7qpWCmv)PdY_2Ss_mA(=$9#Tl@n=)dHotnqpR0T8 z?g-nq_S{YvyBz=i!U!T)6k38~t-qE2!iBI3XFL3VGq;lu!eNR_jcz5A|bo-H`_@zmY-XgB4T{O-Ej|J3K*xAt$FXLCuFRt)W6 z@38n!rw271?QH9__>;H)y5T*u|CH^^4wk=`@?D(Ahqqnp|K!GDC;FcpJt*fu;nN?b z&mNOg@Zo{qpFf$`Z|{XaOaFVXH*WVld+HCFOOs>v=P!B6-u=L<2OnE{>WKv%6I@66 z2cKz4>-hPsw@v8}fAWEKLMeo%u6;B6lzG`~twitXl#qFL$-{{uJrB<*TeJS7i24a* z12qiwdCR_UP0^&F{OjX)f4YBC&yH!|fBe?Sobzx0c~t*eX>t}`^feV#^WOlr+(ku%ho%6&W%0q8l3#l?AJ>_{p{_`BQ2j;Z}fbq z`PrJ(8#6oqzUx8#;keHAG2K5Z@47hhWWu`mGsAq{AIbQ#x%YQbo&Nsq-G7N%QfeGE zp`*P#_=MZYvfR=U-@m%(PkzrmHFj|E+g&^6_Sn)f*Ye$(gj<|W_^c}ly7#uomO~}i zPRa?``{`8q+v`((uWPvR#4WQr6%4vf|J0jbWIq0`tHC+wt`#wpB74`SjLV+q;s52J z=SNf>-@2yqgHfNymhy_`Yzq4;Z zbFYK@za2Yh;s+6j#}1e^@DAT6_CET_B;DJ+i)Ll79MH#kV4?Q2+jXI%%4)v2bN(ZT z117xrUFEjZx33Q9rH?z97&@`TXWEI@lYg3>^`O^%x6fZwwWzJAeEwsd^)EwcX5LnE=KPB9hqXj4yk*~-F0YULq~{Y~-M?@0 zE1i2izioDMzpl3pi|qOE;U$xUoX-sE*lU2*zWlo}|QGYO}3NoZDZVMvi;8C1%gNU+nXk`AUXg{iJ5wCx`AU zyYcKT9k(lymw&5&Wr~h z{Q9Xm59ZAnws`4VAMV>VEPMEdC$F{NR+gfv?{uz%{kj`h-!P-o##@TdjU&&w$n%+u z;Gx5Zs2P5mfhVf3iMa1?w~TN8+-2G`+pg2x*!$#H&g1{S^36US*S**={-ZGWC4Dy^ z{m6E6 z-m#*#bB`Xw!^W5ChAt```gUihb2THLo_wqG^Y@;9)INRIJC@_`&YRG3X8GE>@nw;t zdPV$x-}Hx1#XkLB*k?VnN``mSy!MZtrnDiCot}BeN23b%_FOXLlbz4lc79oLeQe#R zS>rcncmLfpPUkEGXUrOZ!F=7AcfB>5F=P72ExWl(psV|ld!8j9^=ZQ+whrleUaw5p z@_xTt4%d&HUe~4W%jy@ux^s(W@WzVk*Iwsz?eHU?2Su*?X4CDyPibb{m=LY;dUNl% zsv8F$?`T*V-g92}vX4Iv`CI;~cc*VC>-}EN{y~{%W{!XK*{R+Ax85@2p)=9FL$6)^ z?7N3&=NNOg{<$gV(7RO$5;Pt$p6&EAg9`Q)b^AHiK)uJ6^mnVz+70vocY}L= zCaCwi6?6f=_1n+626ytu-UO5`T?x0&e8{^%KQJ7O_?a+__jw8^xl%guTfTMY!`%;_ z1^?GI7{q%#3~m5d!mTSGQhi=GUILi$I8*ox5S z<3U12SQ|q7C-8hig{^;lMIg@wJfB!$ehxgJyxKN6Z%*u}No5(H3;XcCzxCT?`ky{x zNlVs{RgyVyg=B&30jt1j$r?}&*6>_~WDi~=*+a`EXZR|~8M#ujomNVg%SuUiStY5i zYb3>`Qj%RZN#dxD5wio9EAFockAP7?#VJ2<@AZ^+{G5=5-!BeXCJW4qWs(0OgU-7SGK-qz!5y;8Nt&-z}?mKUnG?zMbe}^PE)k(y#-wgjM7oqYS1A&V5 zf8f5y4R=ONG|%|c;_#KSAYcjHE|$fLe>41>;orOxtd?Z~@NX%X#ny6J2@Lw+Z9t+Wd*;ge0Ii8zavPafR=8$U19>Ujh4X%d&YHUCi_8%Lde85lz zd;E~|B-+pY6G|C2M58WDKd5ERZvJJ2s$33WwB4(a>s8MNEKA z7*^##KD_4+ua>Og+a-NOt)z~qm!we*lIXNUVn^0V_>liP{~h7`Ht;m?04m4vgYGAJ zW!21&St0X6m&Lgs_H+@FOEOt->+ zz-pOfS}o(T0b_KlB^Uiqze4%X@~Udd9JNEzhc+Ms_1J(q$wdzGK>pC}l0OW27*+%4 zHN^k;3GQd|T>7w9?vqEr{m4d17`0PkkcZI0|JC?U#d|k_$AJsDB-RfY9x`uE{1TZP zwOnQfFO?ZVz`9IkT9?Z#xSs|0v*CC)T+a@!lsO@lG8fDVS0Q&3;nXCl!;}m(O4iUF!~%_ygFNI8Yk>25biGb8N7P9M z*L1E*=TqQ42_%4c_>V`1qKDT?$bXmr>)`w$pmLEa5AlQE4}IFDXj;O;f6Pr>Dbwvs zWg0R6G}|(n8nj%d2CjtH)iMq4rv+8WblW7@6&-Rvdmp$;gOVWln!Euvh4&MpqJMiy2Bm-{KK`KZY z)hNkalRyGcyvL1Hb|1ihB>V>t{;%!-)!w!j7y|ScbKm>!#}dYI5Pw$sDw!IyT&6@U zmlwiU$O|DWWpeN;nQSATL$@c})`E3Bw~?Q1lBuDaWLoG(nT{MxM+T{Ojsk(%tvL^Ir6OucVGb4o2#raGsobv0zxM-P7jxgCLkDYo*ysb3 z3d&_%2C-Ta@p^o@jEz|%VZ|4#hoUk1OU;l2d!OM+{p zBxE~}xAU_aWTOhZuvNwdZI-dtjWWivQAV3LN{MNs6dN~5hR;e#_F8gf@^7ebN%P(( zN${BnpNYf*@#u3b+()DDk#KK!2Odol=D=Ax?Zp{+xwohzs`&)qxv0x*NBR2n9 z{Hs`B)!iQjPT-Q8X1;(wC=2I?- zp3AOG{!Mi)X+F)8fKJD|?v^;9YLK zmBOU;QUw1cu^Xi{67KDr;Gen%{=Ou*3f{?m1l3BRtsXQW3-waW{Suxlv0@i2)lzIG zKV~9NW~`PxL$##%td)4rl~*MH8UEW_QhfJFoX0MSal^O6dxYZMeTRg4G)l1N4zYRd z6q|RG1i^oh*Io(4Usyd4N`U7fa9GS(9FH7!Xx{5(8I zdF;T}?~pKRIl*urqa+sJnX)k$6;xsSjdk{h&>`%O}yVA&~!0l>5az26~u`W=$vN3KN2-pF$^ zy0i9*&+HHb2+Fzv6z6_p^(!2L<#r<&me)CRdlfUUE}6 zN?s!U3vtxDqlw`nwo7g}zC4tCcL@9k??eXB^T6G${0HonJo8@3H8o4Np;@y0_DQ;K zzohyekYt|&=stBX=WV}f{#jqmvo~wH_v)s3>i+H;{bSc_BKqH~i7B)!`hBi}{x9F9 zlHt1unO-32+IfwuDvYd+U$I`!_Z>4vPT-qOqZ zIPQAzspQc7d7meYTP?BhomjF`QcLMg8;u<(RkmQYWEPc6W0zhBb*4oHgjpd?}U z5{P^4u8k7nRP&qTpY>Drwo}_$-n4(D=KkWxG%hi{HPNvTXmZmZ))dVQ82zUg43lM| zc03p><8@{9G>xXN)s8YL^DE==7;2qk9T=+{N8Nk8jMGh^|6u}k@QE@}UHP|jePWOE z`^;_d=V}5*U;utV3w(ela05<2$;)8SA1E1l5j|6KUbHo?6C z?)8TxQFlb*eUAw<%E^7PH*%`|P4Lf}DbAHGRkl^>lCs5WE&ILatr=A{SQ9p{AH4U~ zOyN3xxjF5Fd4@unr7MsbV2WRXO!6y)(;^wCFP5?T(o1AvjBbpK^&1PuAtwssWxO8Q z(Zj#CROWg|pWt^{|A(;fx&WZ$Mahbi6D1=`K0LnGYut`HX><#p(S&9{qDc<#rO7nk zqe=6+Lz6VDN5?pGWX{Rx(uERIya+5s23AO9X}QFXu8{b$wURKpQj$im!zZkll%fri zTCh>la<@oECOvCu)UZ?PB`v8z(h{g~#evuzk{J#Ek?G868n=?diqzaqFSg3}V2U@D?co*_%3;-n%mOtxfLq&814JBxi} z&uCBCKh9MSPjHgM6P@G;*CXRc$Saec{y>&=-Xx1Ut&@2jSIevpi)Ctu*)pNSWGU5@ zNR}o;qBT)s(FF0Ceo{`pGin0=;H8P!JwlUF-d{6jPG8LnQ=isMp75k*LdoNrFaAaSRpCQ$E;+bP*G#Qu@+9|r%y@E-{Omi>}pJ}AkiBa&c%d;Lj? z(!EIBbXtPQg9bS5{IBuPI=0(+rSJEHXTT`n3zS|dJ+uB*rwKVUN|V0!BL0{Ar+&D? zmL^q+R@qrML?{-R7UDG6sIH6?$sYf=w6 zX)-nq(u`g9oMuM5ye>v&XL$Fkosyb(VN!aEl%=MS+s}~Vtb8fV87=v_lO!j92L67& zq!lfbt2>{-!o!$BlqdN`@h0JyejUMtyl4r@|z=o^0CUM zUZP*^{O>Sm=D%FfY4?YVy1()DmOKC9;GGIKs zb3489W?6?L$C5O4TLODjPfv{b$F$TWnV1|WlfdNEczGc$NnS`#lgXLcGBK+_#^(^X zn{WD)V~y2XJHWdCz&D&J9ag+GDZtGxc;5A38y*tb&3%Pk z4}(X+V?5@%`w^g?Q{Z(D@VX}TS|va2P%@-!iMn0{WnYxcIP68cEGT)ny;UX}ZbL3^ z6xrTQzT4JKK3IK+oSyrHG)^2LtBOoAH6u=@q$kU?j1-xXktQ=UGGr#QFe4McmQ^Y* zWD=ufPM5J6^Q9!6nm~G`WTtPCl=SVAm|ial8T7G%gX^Fu&I%MEknu&Y-Bwfd$z5wk_DynN@o=}N|_~NFjw+2m!UW15*M>dQetQ9l>>wO%7Gz$xb~9+g9d_Ozy;{!z<^-c|9pb% zd$v%T`%RbTKIO9a=^e7?saG!Se&R2(N6C_s8)aLR?@;ooKA(~aB@2A!2JA!KP1uO; z$iuZF)t%-0E!W8V$i%5R{iJq+w=5}$l3AJQG8Z|Rm!2sL(z0cKYQD@(DV3SY6J$!t zbQzaAUy9R~OHM|Gq-PQzWK~IW=5|RO-Xfb0KX{qNe2nojKLdiHss>%bUo&zLFk_f6b7?x7XO7d=w{hjovh z{;+1y`SZK5G0Ju*yXCM4{4I6YBM038a!`8>@&IZ&ifrp3f33Vp&MtULnkIV5>YNx^ zl#(fnld@!SVva0KL>7`tWJbz3nVdF7#-`7a;*2H8GUwhhHcC4C!?Z+f0X87T-YiKW zha^7exWrgqlt}X#2{)qq`g3B_z9B~U6QXrF_-pg8e131B;=D_JeVJyAZ0qt_>)NPw z=?bo6trRYn0r*$?guVa1v9}ysM;) zM#T(uH?;np${y5q2Az={l9QzA=gR%z>Sy1u-wkseL$isJ=uaQ42en|FBaF;ciak3QKumo9HoRlZ? z6H8=f{3MwaJ4Z%GQA-TpBFQ22zu68;MBph24|rKZ{o&tuP6GYl-xK~_e^vgK?e76p zURC8xTKUgpZ@snSH&TWD+p56^f+|qmp;Z|H-7?FIsB) zKJf2BUDp-ynhwYi1#+VU{Tk&t@Bj7rkDolF zcYCkFX}(b#zci4eaYql`;%dY#5gACS5|^}UamnPG&EvdkaWAYAui~wuWv?GLo}TV` zC9k?>qLkwQnfA?R{{=>K8|8}5qrvHrhD>|H# z8ve%3aJ~h!U)$wC$pXIM`|57r&W-IbP3f7{zoEsTJs>__`^3v@zqorH6c=P*6f$rb z|LDKsf2f0Z#XWlOzaQ+A!RBTeU}%tMeg9YIKYsFzUiTaBj_?Rx^CuHN*fX+DJfdpF zBWAmJBy1P=B;+6kki&D!;Q8$B;+4BydTHAZ&oa`@h1!(*J=#<=3r}poy27E*GS_P4^Z5n?Sn^DDJU)7pgm- zpA)4iX}7V~fch4_ZlCzj1L)-q|J1Wwyy2g^?nveT+wA`^?Ef%_{U-)&=iiLpo8doT zp9~^LKEPBj&uIV0{r{?u;|_4y8NH63x&)0fE_~4x*C5{ZdhxW^i5D{99bGG4ad3?c zc#^yKOsN&mRGw%5=9^hBy6ig9=WQ2LLA3-FRf)A^n*@On5C-hnhlFCz^h_Ho2Uq#a z7d7m0lwGL7KC1P(7|6nR8#>EdGoO~4v@p(sjp6*?B$;ZRC1Wk@AI z#M@`Dc>3-Wci;Wu;(Jh>d=JS;Fap~@0`7;yy^8&Z;q!<2V*`-?p#kt80RNU&{`>pG zzwUp;e@A}*PoB{m;5MPgNKMWs9NiCr->^FIMFzCUfEGXC8waS{_+lHhNsXc-XX8iy z#+XjO3UUyTT`SgH&LZU3NN~Y+2`#LVup;WyAhM`h;!CTk6SDU&sFZn=$H|cuM)|si ze20pWl&^H)qIE+SK3jF094uj98B!v%0;b9o^E?^D8K7Kal|=hgORU$rM0ilO>|gw* zeh26VR9#2a&@3{g(^SWvNa=r@Epy00yX{xcS9OrlR>zshi}tQJ%b7sVr=Us_^R`KH_EyQxs+84} zisW3mvz)JEZ`>XqpfeZmBmS|ei@Y*VRH>akEhz#s*kvmJR<72j`H`#lxssCcI>=H>B)tsOqQwToj8$`AZot=n4+ z#=Y>rTfFFL@c?f416TSRTyzJ;8Qz`1DE9s%(ftwV{%|ug5P%J^9FU<___yN!E%<*2 z|Nk-m`^htU_dViUU8F) zU1E;jEdjCA;No^mU;;g=Azy6k-MWry|ET1kTFFAIeyNzT1>dkPDqSXPC(C+m z*mQVM@z|rFCs6zIU+kvd8>l`BWdmF!02{F5!M`}_EA2TRmFIDQJPG@~3ss%}>T!qW z`Hmg_Y5xNQYg&xPJ)+g^79T%s0KH8f`et#X$HmnT8KBp}S&tkL_l;`fU+MlZ3-+Iy z$dHTpA82Zj=d}Np|E?^^zdWONOV6hgJS~-<`l09U^w@gfOT5kKz6Cv}_tr!Yu9@Df zfZ#^4gwm55imr$65-WT2zzBMhqxMQrG`;DuyCsC&eF(X`P~;#K-w=)*#AI`R4X)kw zh3oIVzi)j0SZY7Hsulz?nPHH|Ire1EH70Q0iGLqY9XLH|tE?@{llRy4gLn3mjyOTd zg7Ojg2jyq+ufLo5h`gNiTsb_by_hRdxp>vr@{8I6-e1|7+dyAHz{*%KclaHw|MK30e!0sxDyw+(eL8Q z-rmKCKOpWK>Ck<}Ke`{N_*c5$s{aE`?Eid!lK=MkYnPqT>(ce6P#5FU76Uz49&qnY z9O;EE@dbY7MllBL5VHllZrve)fjcEAh<*$DbAqVN+Cl*}nqWI;Qlj=qD7GM!oLyKf z=T)fVg~MlL3g_4|>%P?hhvZ zA4uNtC;0z2XY@J-4)>mVz=Y5Dva*+>x8Bo;?i(9LORu#a`1{j;?%yPV=3Qa~!Svz= z(~}tz2w1BgHd643u(d-)sJUDv}Q^Y`7?H@>)-+&;CR ztaN6dVD~f7{Zwi`iTIGX*u4@RwND}<_e*&AK?x)G7irrsN%Vy-&z&G2Zg{Ru4%&RH z!zUy#hB7WkU>iWf0~7yXVNMr6Q*FF*#I z>3dfJ)68@c5;Jcq5EmX4#{zQB|e6p-l+W&8F4`D;fEwV z?1+Sg9Fy=M`abY^8POYdLLD6 zsCfF>Z|XhU-do8)e<^=xW~(1)tFNkhJ2lvE>U+z%6?e*pjBC#N-K8lRc#9@AJhVPl3Za%<^=RA=C#lIW9Z_Z#O7|x!5D0_Yt^C{j3p^t;i)P4+g@~qD# z`#%-y|Ku6H$NC1pU>=|KImZF_8F9=(h}kCza333akoP$x5%6yhJtE=3N5xM5KRocHL|TqX5;`-M znGi284x}cr7D&8Wus_N7#4zETImTM49M~tsWGkSOR8j+<9TK}~%l-v$_uekT- zT#b)mr)c5b58jP%PMeoliAjTX%@W4G#110Zn?w?qL?Q!Ge1<5_XGGgLo6epwhMYkR z`^2Oe_@}qqZrc#WVyoKH5B%SMZ@>7l*?Tzyz*!#R#C+ntTzq~e+^0qzkfaD|efGn= z*I|i5_aosyGUO;e;25%YLhRO45*ct(63~NO|7xks&X=zno~JHJthIywCP&Z0?Oavf z8ClrW>3u2EsQiGE0c8h%NnfDeTjhqIl=Y8I#SWZr?caE)jsN?lVe&n)zVH^AZs~L& zI&|y%mZ1H_Snv=0&}$vgn#l>mak~t-V+&mI2~J=n7!HPEi-%&9hY&Xm;Y`dRZLRe8 z{DFU!+r1YI0+*c8yZ)y8qdd*!ADD>sz5L;yxS^H%Ch^fX5sU5?y>5?~;5`7|gWx=r zyo8W9E}}_!C%D$?2=e~b8JY1#E~mXB1e!KQ!P=p4YRv;RU_bj#Q#10 z;>Tz1lfu|tQWUeBb0GA1MbqOINskx2Cx;)Egs`I$7kX4;6yQGEb_5)iC~ClwfhVv5 zrzDCxfRcd>W&m!Ej#?p2&zy7g!8rO_T5Yal?bYM$*MCbd!Hk3csShAXgt9O7Lo1Kb?^tK9CtJfqjCb61;_ZqX|y_VM0k z@_U9x@j~Yn?>=e|0{1%J&p;l+A6Usr1;ce1oJV-WJvr(aa@4WpDr5bcC62fy&fFw% z>CJxfA71WiJzFhUy9i;7PD_GBF-;>`yA|jCiElhz<5W z4%mRdt>*#u(clW?gsBJ=%q8fIQcfqCE2{Z}+Rx}+Hh*of>!bz~XRUlKiuWDtH(Po4L4JJ6L21cD`l0(qVCH@x zzb6E)!#Q&nsko;`6$|1yhZwIVR>MyukcUqQAfLmz-OR{ZNwlqdD<+`w){7SQGX5u} z9pL=$9w~{~3-(Eo{h;K99hNLOPY*sODfs#%?0q6Sp8)Ui@b3Wp$61jHWFVF}AeNrM zaAY{cZ&501{gecD@{;Y(9F*p#;athU6Rq60%YgC^D?3l)wJJaGi}-=|znk}0wm|JY zZNrnK;ah2NGX>9`r8b|0D6ZFI3Nc0czX8ve&qVJ?D>7z z`+2bs^u*q}V~^e7#Eo-+uGEZNs2e&v&@3a}>t)c$RSo?9$AJsDvHY%hFXk2a?3DyxxaaJ0B5^|! zwj>jOl49HVd5nLhng??6?MM9gi=UjjUq-WE91Z`a^!F5p9gqU{dAV?%3GeB|`YAz2 zk*OmNB*K4U5a)dYkpnBRAO|4Uav1)}FX}eNu+FL%Z;;qJnWgdhS6g+z-3BN-0F+&5 zxb?g&?Ucf6RSoACzwtYiE$G@XRCC{o(3@g67vJ%_^#wP{`uyu9BXyOSL$UpVoa=>u zBevfF_XhvN;%7P{I@4kJKZKqh6i@Pj9@GXr&_#F7fVvz0 zH-FG&XY?L?#5meu-S(Z4v$Z~)H}!>km2*^_>)=?2{qW-ERC%lLmGwVC-ZO;Tn@2FM?k zum(jT2k7-aB-wDB8AvLJYYKh8DS`C;2el%J`w14}Ly!RXapXbm?0Z6WTO(OxmG4tM z*xr(SU92<@{Jd5F+hsu60`9APOzm}F%B+rqcog8ENnzb}|14#E9M-{ExE#K1xpL7o8w(zEBY$vVS^&jaw$zB=+cI`(()>j(FK@T#C^wt(Jy z7iWo^#NT%(y1x_OPaYrr4&}9Wlqvf#&m zciZDj_Q zf)s3JGX63NBwEQ68>uhrH?{Ns@DKdkIt5Gfpf7%i|Mn6SsJNiH4>CbasP>85x;eGU z=&x~6^_Rzhqy9&~ZBS@r-R}Z8-(aMUV9q}_W1fVX zCtz^Qli0=F5d1tc;1BmEbl)Fd&CDDK@MZo4uMY%4AVkYd68@c?pGU!a4DS=me1b$B zJ=&H!iSt``GRkLN_kXj1KjQ!C_!p@6lyUZdOa%45h+1aB@i?rJIWWxl21|yty^hUf*H~hIj0lL-+Cd2DsP5z0U6xvDqo{)}9nE-{a!R zSy#_C{ynh)p2Ps2=)EUC*%Kb!iT_6qoBHxoH)s+#XC5_tNXgbfORbpn)Nz<6qK7vl zHrs>_`@^>x-UA$0a=h)_!>ff^6c(R4vHI3aAhHmQo`)b8;cy=TqL@_@>qBog^}%@k zh7TgW)~P(hzq?(=|0H_HMn`Ue|E=)PtUu}xW5SvBMGRR&9-%O#QSw4K3ktG97RU_d zd?2#{(#bWYfmDzJqRd-}L6@rhPH&*jGPm|*DH+)KaJ}rKe)z*)5Zzb$-~3GLwej}X z|J?`wnSXW}|6$<`EmnM-3A=A1<}>2+4f+%8!A@bXUxfb`#oPCkc=?=wd-$gx%#$nd%+##-4k6QNI~J@tpoHO{w>@folRSH5US?3F_g~0QV+z*aZJ(^gjSt zkb~CQLTbhkygO!()NzG-{*6K)Jlo(tn13J2EFwGHM2l?29T#%!# z;R<|DN*l7dX7XGtGocsyC(QqW_jdkQ_uSkX>$U4XF`vo}w#R_V|2OuS|G)S<{;w~+ zod4jamO%4SxNp^cz0!U3-od@s%i`nD7LoP?vYkmC4>*+So zpMkE^3uMIaoBUegPb_anZv)u-S&)N3 zf`N+v60rM`UK^X{d#9_tmda}=s63YgKe0gnf`4X!MU+diotdx^%yC!qfFqd&j4YI4 z4@#H|S%eJa;}`On5ti!!_j#@zIpLcni?bo|%!FTJj$6cMXw`dlopaM1?E3juy>Hij zxL11sM=p^2JMQ{c8gEhaOMk7~W&DTPcC}c|#~pTGkM1kGuXNwn`(@4qye!_HFNwDo z`tQv?KDioI3- zMdiFzZ>*}dU;C9_bFFg^P0yZPGy|C%;`N&6J_$F+@CUSy&Uzj1^RKo$3^$Lf4^{jHh57V&Mr=Q937ZF}hdIMEvOvDZ^EpVkMR_c{ab!1HDC z@;ptP*XIA>-wXadRgVyPcTe*U@gn!`&Hmm8Xn|h@UCQG zH9ldD!#5Nl19|v^JjFFWAwP1n6d(_+KsMk$7bL;|QpNw&8z)QSV}EqSb;`zbZrTy& zt2l4p^CJ8Ew?f5%JMJ8ZZTOYx*IdSbh^@KBY<`jbKJmUE-0Sf9%(U?Ke#HSVWWW<2 z;OTve{r@rggW3Dj7wAsy*PXhXJ29R|pz778o&$VhJ;Zj}5R9BPu^&ReL_-0Shr+AhCXs7rKueMDcH;{Ho5c^$AlkmWr>`Id?Nq z`z+OSsRt_V)&jNn_5!N!#^VCBZ%#UE3=^Kx#E13Llv?i5j1PPAzFFg#2VM}xd7g;H z=sJj8A|;W_xW59szY5*wd)@4n@cvI3P_{sEUx?i=#2yrI%~NLst>v)&M4wZD^! zE=Ocp=Ng&YaizSVnJ&eeVo9aL0_dc(o z_piYH%i=;F(An=ey&ud4;LPVp`tC-O`y3hEB%{cgx`Z`}8##2(@SWmCZ@xFr`!GXO zOK+$aS<%ry;ztjGo*J@=_@Pw>D1VSQvif2R$PHNGTtV?4s<doPurm81pNShrh2VvuSZV0{~bB`Oty6UlWgqr=3ka}dF@bH=X2%p9p6|K(ed2; zs2(k)+02NIn3hc~`XMb2oo}kdap_PBW52lrS zX2#O9n#)}HB+~{tIM)K#*nNlJf8x*B_cffyF)&+0%_{$`+%DrkAoxg&pXDsE{8?)J zT=lOL-vMo_47mHkzZU+Pb>>W7a1{CBk<!)qpfxH6w+5jABmoG;zr^JhYZk15I_zoz-KS{-aPFn*N^R@k;aFvV{XtB$c6_t*3R6bBG!Knvata_yPN&>OPq)Ll{!r0Q}$| z8{ml_aM!^WE8oA5%j+drzSou1RD@WA0THhoH&Q&LO+c=@T8~0o9BE& zo5h#cXqlg90sm=m8t?3-qx_gG&e;o2=%CjYkMEk5w?4*%}(?*acF@b3Zt z9_{?=75^{O|NkQVpOBICzYVu>4v4z(u&`zsLI2dK2zmm68$ETNT)jAtx^qkc(;x~-#GQhbqBWFxaoHIAlS72dp5lkPs$*X4i&&a)ct4s2K_ucbYd;#%a zGWI_O{ZCc=C(Yvw$O6etg#UQ>kB9$Q_>V#V`L3u!W?-pYU~U*QqdAkFNq#$x`OwM4 zL6P*mhiZS@^S|5H^D_N6+D^21!@ry2pIH`42Hcoy=k9mbadk!iU4P*JH2j~0|6?+O zez;-uOAQYPcFqORL+KRB83Fof-GOH$H9_RS7dg<;TjPhH(1#HJ2g5Hhfsr0_BXeVn zoGUhvQ}$=ZfQ_D0gHL^<*1hTH?uojbe`eMt6aOWn|EWp%fMjBTlm(KLg#Axk%6Eid z|KsuhvBZBd>m9kDTj&{IqLt3_%%Cq4x6_6iqwC_zZd+w!oQpGb*^U} zaAO~!(8~QQ?D^1te_{ahDPsTQ#Qw|&VkX}3P-4Mw_5<)gDymtW;odEpvxA()^uiYS z;19I;13%&dJu#w@y@3fCFj|oTddv;<78;qS97qkypxgO|k4K|AEB15WF5|y23;v1y zQWD`mc{b-i=h6#1pYvdgBsZDw4M|)f`3Zby4Br)(8@+*<(98^{M<9b5a60?lRQ5i} z^!_B!HxWiZV~}?HmCJv?o1E=92jHH4pewTt-GHkRyKf}+Q`{S0a@c=o_#b6qAAk)Q zNw4gP5YB|sJ3GpL0R5*23>k23=bzb$zMRk3aVFD`b9n|}3};RUGGL&8#&PC=Go@B~ zEjj1+nUB|w$A50(+urYA@~?bVxn3wW9T zH?{HaW$C+`1^6Pu!=tS8#!U7ypyu!al&2^AE1bfGe?pD>C33 z#_T{ly?_y%8N&BFY(I0<{Wy>7;9lv!gMV_t_y7yBVIX+|ouMx0KYZ^0>yIzt|K58a zjnB_rjP6f||7qy|bof^`fbTjX21rj{BI)p-2LGw>pBlYcQsF<9exMZiPeyhf{L>4p z`u~HeZCG?yrv96PPqz42-sF5I{@+B*$6Q0D`>p)H2+!nwl+G*O;op@UfSc(gXM#^K zs{wHS$%FlX2WKNZ@CBa4177r#`_NObWlyO5zJZ*O;@#u`_sI_h5EI%WhzZO!qC_|CCl6kgWCs z^T0y*UrKz)_xi?G!2bqGCjLw2d%{wP|5E4yO(wUQKu#l;JV>xV{R)OFGyXTD|Js1J znDammi1^`&X;)Z2vWGm+_yO&v%6+PeKMJN>a)s zNx=@J5euXx&4K&*=2InyaQ2A5DK=!EgfOeh zV!AT-{{ir?GrxsCzv0LMdl_D1{t7jJ;(ZU}Y2*RUjR5Yw$N_u%(Hlf9KnGNhu<8?6 z{o?ApkimSIn4a?^#Kr#Pe9hQM3pt-a=JcppJqmX60>PoR-1IG26lLUIF3B`IMgb0pSCQtW!{z~)vzV6Vj%koU)? z#ghLF=KP7py!DFQ|5*zN1Kk_|Z=OlvJ??sRgw1;6U&D%nME#ljL z&n5ideec8Zskw6`I%%TBCQXodu1WBpk~9tO+xcI>{$PnD5eFp3ufh(jm1Mp%JUN@oWtF4IAGXZMIyQ`Cn_$$rgj@E&6!h0I$>kah5*LSFrD|aHR*(kN!Wn z_i5u^^#|#E=@+6;%n1J`-En5L92GP3;mqXo%*+k3kQ23%7Y}4EhYf@v2NBF@ie~R0 z6i_wgSLR;*x_`-kWYQ#wO2h^vO=eCIaUlAil0;5`d~j0Ie7IjE3CKVqejqU(KR_-Z zF=iukMYc&i^N3^lzPKp%H-Yp3_y=yjBK1Eo@Fes9-r}6cIeNcd=REFfTwmqf*DHYj zU&T8zpso(?+jQTE{WtObXZ||o-*P@QfEn-s)ORh^`Yp`k2&6YCi0{u0p-03{t}K?= zKji+j3^{Z8K8yqWjzx#zz7?mPFK|6f&BtCttu zY2R*Ny3>muCC>7R&rMh3H{dKUvT=o&h^bhbne;?!eyV#$HoWnEzENp%T z{eap29h5Qd!|oD@3^`$PA?|(Tg(}6bkxJ4^D#UlFv3{cgPqr4ZUpnOZ2Qpk1%b6YiFScIxcd$i+6Uqd;n;{n1-U{2>F!qOIJt!P&fi@=S17VR{aSWVt_B~{^ z#mEuzH~cc6|2k%W`A4w#`MbLaT zcyJohG2as-226r6UkcmHVEZfV4{QiE?5{#hxElHR8VxX);V%seD*9fd%J=JSke|7H zh5a9yG|d*5zLhLdYseDGWF73kj;yeK7_&WR|4sPcCiIOh=p)9AV$xbGfj5o3 zCSVOqfEDS3e(o7i{)?RdarReyfcR|KAL~9+y!*?TARbr-jzbxq{ZiPU&G*la z-PZ=6pAGlA&9)iyJ0@GmidZm9_*UHa+hF^hq_^(_ws;|_Y$c=s2ZhXvJQvts5C(i? zV41lF{4)K2I^A2JD3rMW;ro}!@!ZFHpOgvKe5LRKblG3Zz3+9+`#SnSm;Kc}?5{=a zo)P);YE|Lua(Uj*;oI#?U%JBnlO`knCll-caT~}Uy%GK&%=K}v+hOx?r16AXw~^Jl zok9=?7Hr#v`+hHJF!n2L2T5it1?NCD3BwTM4$Mej*xwbHlTN=-`)d*ZAya(_AMSg= z`#O*H81wT?4k$7HcisOQ#C8WG=3A>Q{4F z43J_T$mRk)`+yvnFwFPE?9b-^YRvxw5f7tNReU8E7tQ{e?Aq7MTxtI)zqT!0vKYI`Jg>cwh-S(F=`{Ugo_U|48I-dbueSpmcrSJtZzpoVbmx(b4 zfbT~M-;V)2Fa}M{Wx2T6&{w1UjNki-{TD3SO;L%PDIy+Ye#|z^19sq@Zx`l$dnv@a zpG>fOAlChK@cApj10l8Gz7MG+UvSTO16$Y~*y66Rzf)){%>i!EEd4Jc{)6SBJO*)w zFq}NGPJiknnernNV(pL30oXG@%ANsT^8oe?fJiV8l)(04vZjz8X#JDw(EBroA;E0%SX{FhS33*Xh^GlfjGvDht z$PenJ&l;(#*}3qFY$@J&Qx4HI~wni#BU12=U5>c#<*bV+UjKM-C?AhmiLjOs01o%;xiubNGDL0k(HAnodLBft+$M zncsFWhP>%uva~q_7>_#06m{(R`it4@iMs~JXXHA>X689WXXHCXE-ZAgryq2%r5``arF+y*k*^|m?I8>(Jc_tn_U02*B& z$}*>C*T3+6PR}0Yo~L8i=k)4voGW)$ulx9v&a>kC7ua{Fbe^@l+*PEeqATo4~wgd;0=H8^)olshcT<2iL6@47(m^1@!n zzrV6PfGe{*GMgRX4eE7#Xs_~5uGjIa?%#7o9`xy|5BCq~dqsIluX5IvWu{)w@1r?8 z%Y$0j`LeppLpekISRQ?Y@|0f3I}G{b@3VRxr|XwdQPw`)zlYvel%e+(Whin*dCCpS zuDy=qLRb8rt}L^5>v_C)nVF^Mab}jDW!BC;%Ts!lU2jm%!g1D5*`D3OY{&X(7Wbk5 zPmdO0f$MINY{&pEg##blc)V6boigd)`dgsC1^Qc{zXkeRpuYuf*a9pcsIPLvlilJM z`f~kSJoR;d#;(h9^PlO1JdN*6fUw`($&KY>{u*+(AFqU5uMP?vcYxgKjp@&@S2gCDub#BbSbipS#>z968LQ7&X0AD7owe$W zb?%BYA@f(9G0tCmCd6si>o(^?w>wmcAvh1SIas`S8k1Al{#385Gie@6&MfeF^~?g# zrDswgarhkNo^vMJbIplZpG{BPp=)=Yrd$71k3;P#^T6pguY?xPEu)P2rIhJZOqp)r z`SL8G1n)|U_Nt{&rvuuqAK%8F^`WT{F+`)DrC+;6zy0!7#dg{u-$OeUx!{oAPn)n` zCEHK0O7bX!4-Nva^)qkdnpgX2xBf{UW$lUc$|-ejIW1uN&nu-2#}ZoLR7y!M;5%@y zA-j7WnH&$^uKsNNU|7$L<3Tgu!6kJ=z>aS=DYw%$KnnOyGpr_ zUX_A}nGcRWuXT4#{{+wK_PBX9lr*oJ(&krDnj?7qAW4pu6zc?xUza)xg9OdJZT;_u z-X2W%DH9&It~74?Y@L1wtyS-&^_tzZL7Ph(4f(V&AfMLh_tOfr#Vay!4?+K!yJ-J7 z@A~!_$3{wUY@kFZaM?N6QH(S2&9S#T*OSeqorskv zIZV;6!1Hzommeh59sHASO=N}`UBOE`@0Ra>hPS}#&&GO9WN`M;r7`d(gdDG(vk-O)|*3h<_WNJ-vJX|dp)w;!NP;7eoyA1}jD zPU+x~O#`1`I%FYm6BjD0C>5O7al#S`^WAsX^pBF&wwrx{(dvUfj=jns{OsW0RDg$3 z?gvgLe_*wZelz;BvHn4b57T|>^cQ2}Gq(LFX#qI3Qg%~HTpp!G90a#wF)a)( zqjW5`a05rk60&Y2Cr8=S$sB|z&m;$WCUawA@!ebQf zi}A<3d$n%pv#EX7ezV?fS!qt>6T286r98TEh1;Q1yP_&9N#j7bx zw1N%_Wv}A*z7Q{n8^jSZ8}cl~0Wt~lz{VN836qEOoQ4hLX$B7-qLW82d&iOq{QS(l z6qB`&Vl(zrTq^jq;tzpis{)+6HI!hkqa^S_rGir>4Y=V+z>tmwmatv;I)&igGq_dV zmj0+0vk$Y^M97T)hTio_Ua>(hpHgQaQ!O)PipS9Fn#MN&uErD!2qv!IzK#4#WuA z>l7+_n}U2_C$(F{E$feZvHm$8G6y1psK1u*^bPL3tmC1BOHaMx{>>+wU!>0uJVBRg zA0cX*1erqAI2nS^jrd;!gzY(b6niEp*H8S8s>c6=O2>Ra`6FAu+&HZEY|^0WMlG*! zi{gdmoM<~Oj*g(0;}a<>X%VHRuBOCv@G7MhK!0$i$AU*E8ayhIjTCEdq$Kdcq<}Lf zPIHpN!7XG4{;1yXZBn=&xh4If>j20j5O1b8L_-;a7F;eE-Fms^{%@#$0(6_$sTcHZ zdW`7sH2S9TIl55dL2vI<(2;GyRI?$3J}SgS;PAA~;27SC{eJ8#AjjzN6Yo*;)c@hy ztl?pt4?N{{576c6QS^D?1bT1VG&-`ewt=7L9u=dKbmV76F40 zoHDVs;2LYBc<`u3fmhM0e20R8#jEiH=92sITh)IQboSu%Hu21qKlCKkfE&H$z7DSJ zI&i3?4gOU=o$A(@VW)MZ0iV4S_&6QG@jf5oD0z+MVH}$6ReH_wALHl)Pfi&oG7BC^ zT9YtqPwvL3%ZK;M==UWv>HAvna#s%{sv1m}%I={*@10CCgNa zPHe0nI(%%PpK-*CnD%vzCm&%}bF;>?~ zAmsz7z3`q-W<9~PD5Qtm{qd~#@&|{bKkO~&)Su}NE{}QO=bQsP@0r4@&i{u&?-wD; z0RskT+!dQo@Iz{Wj|ME{@JjNIsv@7bYT_qVlQg}YRGFn@%sxOXR=rBiyOi{KDaM&f zEHIYy=$nJX=>0V_s5IJ4t92_VQ?sA!cn)eY28w)IZ$*D*e|GOnsbItjs=&f#8FXiY zevqc%1*6^?g}kZV5B&39g5%@{4q_MB-Wgc-j&kU)g#O?$nXPQ1=S4r6|FgL*^H0gx zd1iZL6$*lC!FgXxB4Z7S&<3KgIueJ2?-1jgDz=Vvi8U0EQcb~WRb_yoCv$HPep{ekN>4?I3EDVu4g=!*AW zHn)8o!tmoX(`Oo&3-r~OeO1t13ru8i<0^rNrv&Gl8vL)?Q1HCjnkgWnk%D6IKABug zLQPgtd7Pa3r-Z@TIf5nbFYW8OTUTpEveh z$V5sV6+nl7{Vg{}{xu5TAfz*R0q8%WU)q-X>A3367Qp!wi- zoC|)+mtg-F1l{_xxh?aZa`=glJnoVx)R%tcBd;O8ydJoD-~j~pfliHg2=Lt)z?pkB~+Ld*gX&79OV%@Yq{ahba_X!C}T)vWHau$=@rR z-8XJyM?V~#8FiS_tj&~UIR;LtlN1*GI#~iS=QXsES^E}#`zB@R^XT)US-{(R5&H?4|n0F1BrWhz=~60DDw&9J~@>cM4&1KJ4!!J4znF zad(9-E<#}3@qumVvONeFVt#Pulh!!%a%r2!0^&cVY~YLv+yH$Ujb@c&3C2 zTPRG{435M)iZ)h!Wz`kT!f)9#!)@%Shl5`ZZ=r?Y3r{tkptyiGih$j1&^=858d=Cy9PM#OP`++cgLDofYNu9|!%H*p5(^@hB|-UuF{K zd@;~D68wn~I?R7D2eyGrF9cjFDdKgGq#EExRnNTH-3GXiF`u(TpFa12u7;X4oHu0h z2%c-S;J$6amg?^q2d@m{y+r;7`tcj&i)WyZ|4H(J|HB*N>2sK-O}DLLx;so$X3OL? zmqfw_5(~iJ%Ll)sKe!zQ;K9KE0)+4%@xh7a*985+ku9&I2*sggUDw9GQ~!s8U$NEG zB4Yz(0y{DdJc*VVTE>qaw8@fFIlyU3ii8Ev6 z(z1Vv`55Qn8&EL4Il=QC{sN5v9Pk40+(7RTe{jQzpu4Q3I)q=?bFAv@{}W+<__|CL zvrh_J_XW7Y#KkN$%fd&`AdUlzcqfAsXnZ z_OFG&XM(*J72Y%T3T-Nh+R>nx=o=t^YARBO4x$yIJGo`#m=Yc5&EAd zzCSqbpufNH1nzHe*K^}rEy*SOzfz(vGyN5!22!D)Yhi0G^A-7l`_B*jkMN&qeHthb zK18dyy4~WJ&*tB3%;~vx>z`#Sq)byDy=*Q-KPaMw#u7>~mQga3V64ADqTmZYqVP!J zY`^EB{Eoi=G{!;5k!e3r{rzlAzS*r?f4$~JyHo=HP67Dc{LYX+-Zwe@!R6qGvD;4p zjC&RAuc`wkEcBN`e>@M>XagPELMLRtvTEp$J^it-nU|2Iha@vlN~sKmYUOi#G7#zeV2SR`8x4CNFIR z`RMDxX^Z&{xU9sO3(3$Yl%i&CyweGppAbAS=pJZsAS~tsBq+4 zv~NTs?HG25Hr=!LU&{t>->V&1vY0=zK0RtHC53LFl#ngZdnfeYN9m>lN;ei!dQd5) z!50yyE}=gjbcOEIzk|Nb5EJfsb`Rao)@^^O_H?@+cu)K!?~||aJv{f%kvlkTUBF}N zq-!DPz-ICYZU(uG_mO@8PG9i;ir*(M@p*Cw=c^0m zUQPz^8sL4z4eu{L5dUECd4ua#jCPT!TY&X_92_v<`{bX%oWJRhD!8Ddxs75 zoI2@2TLLimqwVV`9=t25HrxZ&J(OX|M;|x@pE%Y&z#C`7_!A^7o!N);-pp6J^%rW+ zwR=H-FK{1u;U4e=@0B~Su3go@^u;{XDHz-y=40d;a+Lhc9en1Jpu-$@y$tURQuxPI zvevJp{TQAm#m_iBUCVqrs8?W6{dw?L z_nzB!>3F?8r~jzY4+PueR)Tlx72E?WxN$Jj4(=InPeg=*XBwOXcDx%I1F$Bmx_jfF zQgyyvAo>9Mz6*}mvmDoN7r(O%b7BSfJ(QRWs8!G%KCJ*P{8RxApX-$6ERN|`wr>5y z;u!BDx%E1{Z-2I?Tq(Q!ttG+?clj& zwukPF-%=@Nyta(fmT}o44l1zbQlPrT^Hvn^{7tw1w)nO12d)J7@LKRqf_o0nL2JY| z3Ju=}{*hvEi`J0}yaNKmomv0wQRnXQPpvxF&T&3=^8ImKf6$$A{B>|UGG15ckLPee z0M^O%h0#6Eb1NS^?*B34gCmnRQfMUOT!ij6aBYTf0@oh6*1~hi5C+~2aI1>UjpSu0 zyKDAWtIxv!3C>H7@2-REtb^x{aa+9sUMsA>!Y{68K3!eWjyu3*$LT)?`p2b!cLvY? z@NmXAx0OP}nC?5lGnP;CuyXKBHGylQnVbVE?wbBe%zqf?599mc_};MQ$~c}nxSbid z)9a+gTvxBIY6YJc<4?HVtwaB@LyjvLeY}Q@q^ZQ6|%?GdEA@HhIgIlYa zT+D~*rGUHg{A2Sqxl(ifbH;nd@f|U~8*p7o80V!J_dk4LO85i8W%vhh8nJkmJF&5N zFvqduCKwXZ8UG--g(IPR*nW<0Mio*Mew@Z$?LQE!UIoCd*R814Dhd{>;>0G z9=KPE!Le9FS{pcouvR3nA0_XIR&owKPA_Qc?&S4x`5(8SfRD!*jUSFP8Q&WRzKe0- zx)=wZi*ZKtsc|OD8{>2V&3E#>tNX&XxNQUCGWL%H@5s3Dw4!mLi525av5n(`qK}T# z#vC6fk3BI?6x%k=%icB)yb^4@?%(=bpuYwBTcE!M`dgsC1^Qdynk~=+GT`PuW&_+I zdonZC3DE-4z>CWj zdpK^cDB~+r*!OzuvpUMGEqDVu+JQHyb3e3mKf2d`N@v-%bD!0@?`%h2=YBxvzN>wQ zc9glcX8;?ww@rr<&qIumZk&iG`f(!A9Q|8=3;cg+0rrl6J-HL@aIN#-?zx$t={X3? z(Y~6n-0AUyz&Q{^~M zRp!ipLbFWxTv|w!OUbRg*RwW%93q=Kewy9yNpX(*5};HZhF z70NY#+AQBjTV;D_t9&1=lkcTvl3dCZAm`b8!|mj~bM?15?rKY%SAqJM)53XWw9v7X zQk}~v)~%YtT&pjd9E)$Z{*2$&d+3m1`fT~KQ=8N~Xsc=`ZCCH(@|M?Yaw!LTWTF0X zUh8kW{-I8}ZE^FF7dO9_l97v?0EuxzJ~r}^ElyPzgXZ2;`!mb|E>9s^mQuMUcqgsW z?xNM&eY6Jow(9~4X$@jcmnjjGBiw_W)X(d4{n>r;0z@VAGi`h|YVYM&%*dY&$fG5O1IVE*p=E(AZ}tGaqAH*T;{6ou zv*oti-{Mu+#&ToBJetXjyx3sGfd+aVC4<*-(zrKVR5+LRrT?%=D#N)@%z4Rs;lh+% z-!6>Kqf9GuUxSM%GoTc?uT_)@$<~!orm}>RB?rmwxAV5^Z}!b=vv?!s-WzdQh)vQU zR#ENON=oFpNPUi66nRwMsQzrMnFNtcdi+UyeA=eZQ&M(OY7Amjz>l4Yc(nzFO6087 zK^kZQ;>1#Ab;wz*B&&DcZP!1Tzo#u2`JY<u>}#e(E>*}`SCP`ngpEvdS(LCV;!v+OPY}u_L$f1nP$^}<7@+VUcP(lo1 zL~Jz_A5xE4nI=j@{Sy(lABo%*3v8@+tL}6CaXr>%EU$Gs#Ov<@o_^mfUQU5d`P4?i4u;B7iEu9fn}HPW6jCA4|uZd!iNif@w! zrZ)NW7Oi`Zw|tS(r#Uqtjp9?5QOts^6v?=@(@Q8O9=RV;hz~~IU!n#1zJ{X|r#eYi z#2f_rzeP&-raslbv+iTD_kgG_`l{hsx=`#! zr*lQrwp0B5rACKpYW@{uYBL?4`X=_jMcmd`h%ckdH4l9Mb@Avgf4ke^hm&h(QR!j< zZBDV#%7g{9EG~yKV_5E92}L4*BNq7^38teIg;-yEIc<+kq!lr*QdZOsibuXun7$1; z8|QF;okz~y$-dT~d8oUXs_ANj7`u;~MT^hI|+#8I)lI`mC0r%usI zb0qZ_Ul9Cc{C^1dt7z2yQ!ReRqQClBtH>*=g1izcNwN@F04r8g{El zD;Y|^-{wHgnG)J;UPKFZd1OW2js|fILhloOtv~Dc{&ZmIX)ZUclt-6J2ma%!Njxpz zzp#zvhPexn8z+Pgi1l)0IdQ7vG)rE4ai;iS&-NdKy88?sGQ!}g+;i4H5IIh!8WM&< z?DZr=-jh19nhdE`WJ<53l*M_Mb5|$Ohx=yH<%)ag>!N$alVLoRUytxZ9)tha<~lPO%#NC));f>pT_Vl$D?4E z$f!EXh}}<3t9A5M=~%j4K9D|K^DKQD|4=gO^#p|V@9Seh8A}MmSkdNYxHE4HvD>))3Z7yOD=g4X=z9=kW?LP#<@=DY%I>l}0YpS?h zB$*uX*>c3ID3N=mLoSlBnT#QbO%AL7>e=U|vB80BDiWe=C2 zH5C;@d3HzH32c|&GB@@3R-(h9^8d{y!5&$wLV%5k64@*x4J zA6s|6=GLjh5a{6Z@3Kk1uUb5w62q5sxj|y&NAU4%@j*_Py9jwfc>X&2)m$8N{|tr= zCVlYX*-?B|*%$tZix!BG6M{acMedJ@OElZf?ugTgWP*jV0=rVTNVNUOHUG*tK0yIib)^VF|t*9aZz*r)p;Pj}zr>q19Y z#D%Zma$BT`-x4C9-dA)2c`bE0rJ+Yu-8(_ zqL~ys8hMA$e96V^H%|H-`8t!YX@Dyaj2tw8Cz7cO-ekEcQW^4c#BU)lr49Kgh(+{8 zJf?T`w|IxL`uc2rU4lFW8RkV@xhQHu9qM0?JS^nSARi-AR`IS?RLI_4*w$J96%~t2 zmB3%AqcoOxf_#%W1Isx%jNGGo+AND^a}f!ZO+UufpXHh~KC+L03DT9JiV`InI^kQofjCghGJLJ|-+9BC+{R=Kl@!)K^+INMSG8JGk7YV{3k z-tmQw`io23q-b{$A9*1xF9LZ%{+J*7%h1ndH6&NoB1QzcuIL{u_em#UIWWkD@I_7l z@*vEDy6>`utJG*mmZ!$XkfCY6=8e2>FpnRq$gavT?W09zybB=jA(hMhVEG@#$ay$G zr!=$TDR=S#UzQ#dt^%sjP+gNS`pMMT{4QI(m@Fsa9$JJZiKz_P< z5^C#_^Hz`C7L4&C#5Z;2GT>by5IH`Z6v+rg;>jQkH-gPmeK0rlw>{2FNl-?=mTumP zcy;737;_Q7&vfX>TS!38%HIym{YQ7Zx6Jq$I0(J``A%k0&SOfo(Xx%``T<*bc#GE7UJQ(i;h`W#1l+)izoc>NneqDro z0~O|j>=|=28`u86;>I>#De?*sSMQDZLU+W~I%`jmQ{WNuFdinqVB{0%TS$yNTbb-Q z#vR0%V!RBH)E(FP9U4aUPY$9ZPfkGW|4h_Dh+Kk@f0y2$wjq2({sOz@NF4kxiD*-Z^h|!T(~plxK2UHiA3I} z55{i+bdVq(Sf)9Od*LKv1&?2l^Q+lB?phmn{~9zY6;UkqKN7M3_Fa^YxG$FX6bl@j zFyxr%g%v&T`D>l)TL15^KNs6B?}}^x4Y?tw*3Ix5xg)0C8!`O?#IsA0n=A`xCZ+b+ ze-O+5!nID?`TvgkYm+M?BUdAKeIs<(iMaIx6cY@*IK&5s;CYXj_1mt$kEFTH8?otL ziZkSaxO7j%rTfU>_9YIVtG`wsUl9?xoT8)F zBKCSaMI!DxDj4%Q{b9@@a4$(JZ@d0}qQh-|tp6jn(pQGOLX1U1(QinCd^0KXYvhP; z*XZF-!Tq2QtX(2eRNSEHxx-xjRr;6;TjWyI9r5#sn~gx+bfo1FMIz7I9DsaGRq1Wl zUm!T#CPZwoP<#&0-_xi&;sTK)$zq~am=9^Vc<5#_8R|+kiZX6dvJVPy^_S~nD?+%~ zXT-qU5d&)9PBvQ}g;^?q7l1rF-Oc$QdR>?6|3X1?n?#J*M$})7y0e&ODRR3Mi0M>e zE~h~bb8uk!S-rA|%|rXTarIXQBve??|E>1*6c&y+-iWPa3P%iMXcZ~Uc)l2Jzx{M@*_3&tZeE`kxwYKJ(+>%*NGUACyvIi`sxT-%Md)Tge!{ zgS6p=Bnzu0Kg8U+2HgJmBf$8{#nviNf5eq`#MQpd#nkE)N50i6OFeI<;+@~+>K|xI zt%!(4ynOg}3bpPfLudg>LQBafw4Pj$r}L8Gw#Fa!uJEE%cJioH@g8!+&ypOmu`=m9 z*uO<;yn|`fHIcVaclHxDhn`^$Uy^T2*g+vtdnqXF5UCLJDu6G`BlIxM$Ft=HZO!f6 zzw9~#gM&VtZ8Ci*Hix_mIVU!m&xp;Ix5a_Rquyd^`3>JC*h#Lj4UAv7_vzTo0&zsz zA+a^FR&0ztD%Qmw7t7*LihUzr7r&@&x}EixYh1Sf-~BDn-va$DaA#VeBgzQAD{i~? z{(FQi4L}go_q;58thAjx~OZf-#^>O-?FbwmOK@+HFnmnPvd9r{WM|zu1}*}_kL<~ zE!xtDbFg`lf0&CscZG26rz?eQ7&7r-SNX_^={gNHKR3%+gK#pL$O}#C*I)qU56(tW-ZH& zac;(S8^{iPaI0%08J(|teHI7s;*2Nf#xD)qaq-o_eY6zu3ORwrz&|gbObLrw*xcvq z%jf3g+JMV#LR>;1@R{`9@Ev(JUQhpN4@`K(l$fyTZwn&xfwuy@8DMTN1lDAx2L4k? zF|dYr_xbt~rzN>T4D$y5S`~1BnBNM1+fw)l?}0F^LT)X-v%wx7JY=XUBzDEwr1V{s z5(A8nkWxx9)MDMenNonU76bpU*`w&X*T*>rLhjF>>C7sjgovT1?r}MUvRmPYGE7t!bGxI4n`4GiLu(fkwF6oa@9Ps`u zz&p~p)n4=ZI2VgEm`}z5fnTh;H~+6Yru_Zi#ZS=X#wm2M?rHjCu_OKY(Cl_#489FH zPYsiPPgN8D_~rgFAAP)f{0G&qdegRrCR&obm@*T#QG5)reWL3q5%`D^@JR&<@P6gq za@FhOx@>)ECS?xDpz?dZU^tF{DtPYOHHnLnlU~hXw9W@+<4b}o>_6zf5rdr73i*cg zmzUA@4PkV0zbpOY(4+Lb9neoemtGqa9^RT%d7htK9d)) z+FaP0Y{!~r*YzJCHsXN*FL}Z5g}^ORAvQ$|%npO)Fa-mDQKDO35tj@>Nl8Of3byOp0RZ&#D~FW8m?)gCYj%S+CQ~`!?tRA{Cdxl$(|moa#?<^ zfY0!{+JM&uY!bh{|4>LOzg1v8iCas;_@u!al969`$tEuK>}*q9f0Q)KasZfH@b_cw zC@H9tVi1S*zWhlO6+PbAfvxrH!k=`4AOA7g-ECd22si=$erJFi1pR>zz{k27TTfA7 zEm4cL6o!YU$6CrdX~uS3+Zi(FpF-Yj`Q+ho8SvR>nDzkkh^?EzZy#7hpXbl~O$Wx+ zbMFA#3NzkoZj+tdx8(W*AKC}88t&3Ia)IC08#tQ+;4?^oU8#iKwHQ-Vf_Bzo9b_Ms zk1eO-F^%8l-*+M}^4<@V;4@9OY{R<8ehz0UL0iezJa%Bc!xw7}>{)faZSp*~?YZ7; zZ2*`#Zi-V_(>P8ZSP$R>BS;FLu1wmBy!n>nzyxCcs-D~6aid2mVk0+FV#F5s{r3aw ztb!ucO~4K;zv}qY^T(Z^C(m`;k?V=PZ4WuaY&k_9SeNhwMvDOW(J~{j`E*Awz?VPa zD!&~(eE3LdO!QicjoJkKr96s8tcDdBpukz_^YtBZeP7^H`(RDPSMnPY0XtBlK0!+8 zt_y7bk2;`+rC?lbriW>cq0jaoESDem z(dysJ(dp0TXm!8I(HUA_L7qJGyWeno=#i;oqSN=~SmF-m80_^qlJFxr?zYyP7c}*E zCD;6h73%-Oe{~CV_zgP#elg_>*Dt1An9?CF*k?m{Q@(&_qXm-9JRB1tV|b(Sc_?HM z{yzxEd&6wgj{_0&GOaFgcw zg&PCsZDknkJ-0!#ADbhIa!lA{bxdD_cRuz`c*W-XRID+<5%_B^H5B4prS5s~!3Q3h zzev0OcWdDLmc`3x%@y8s(33$*i2oD*4HC+-akk@=|K&*w)((swdw6i7A zUP)C;Lg`ZexNWp(@Q-!aK55wUXlcG!aS|~btu*t+MVt77ihn49k7yM%eHX4N_6(J* zD@+2mU^wvI{#!;O>Z}72l{4&!P3J!#n!gS3VQ+9<@u- z$`=|BBHpKjF6KXt`Px(YJ%2xQ&LX1^<|VG`ljIu&tV+z$jk4-JR5@1pUBM_*vf2D* zD&}7ah`GOTz}*$|9rnJ`z0I7n*yx3r0Uuz%34wX03~WAzxkT4IW}r$PT^Nn^+Hl0= zsihU&x_6ym_N>K5G1gpVqPIw^YPx{uaZkU-K$#}4kYPRPL(ADZ=}&&|=)B%Tt~z%@ zDSxw7t8D0v?>ZpByeQ2SUU4x{8wx&QMUDU$YRJK_-P@$E - - - - - - - - - - - - - - - - - - diff --git a/Novetus/Novetus.ClientScriptTester/app.manifest b/Novetus/Novetus.ClientScriptTester/app.manifest deleted file mode 100644 index 5064322..0000000 --- a/Novetus/Novetus.ClientScriptTester/app.manifest +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true/pm - permonitorv2,permonitor - true - true - - - - - - - - - - diff --git a/Novetus/Novetus.ReleasePreparer/Novetus.Internal.ReleasePreparer.csproj b/Novetus/Novetus.ReleasePreparer/Novetus.Internal.ReleasePreparer.csproj deleted file mode 100644 index 5c14202..0000000 --- a/Novetus/Novetus.ReleasePreparer/Novetus.Internal.ReleasePreparer.csproj +++ /dev/null @@ -1,76 +0,0 @@ - - - - - Debug - AnyCPU - {64A99062-3C1C-4D2E-99E4-D6D92443AC98} - Exe - Novetus.ReleasePreparer - ReleasePreparer - v4.8 - 512 - false - - - - AnyCPU - true - full - false - bin\Debug\ - TRACE;DEBUG;PREPARER;NET481 - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE;PREPARER;NET481 - prompt - 4 - false - - - NovetusIcon.ico - - - - - - - - - - - - - INIFile.cs - - - - - - - - - - - - - SET path=$(SolutionDir)build -if not exist "%25path%25" mkdir "%25path%25" -copy $(ProjectDir)$(OutDir) "%25path%25"\* -del "%25path%25"\$(TargetName).vshost.exe -del "%25path%25"\$(TargetName).vshost.exe.config -del "%25path%25"\$(TargetName).vshost.exe.manifest -del "%25path%25"\$(TargetName).xml - - - - - - \ No newline at end of file diff --git a/Novetus/Novetus.ReleasePreparer/NovetusIcon.ico b/Novetus/Novetus.ReleasePreparer/NovetusIcon.ico deleted file mode 100644 index 8cd1cbe06cb36d095d96e779d231450933909936..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 135503 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 0) - { - if (args.Contains("-snapshot")) - { - string infopath = novpath + @"\\config\\info.ini"; - string currver = GetBranch(infopath); - TurnOnInitialSequence(infopath); - - string pathbeta = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\\betaversion.txt"; - Console.WriteLine("Creating " + pathbeta); - if (!File.Exists(pathbeta)) - { - // Create a file to write to. - using (StreamWriter sw = File.CreateText(pathbeta)) - { - sw.Write(currver); - } - } - Console.WriteLine("Created " + pathbeta); - } - else if (args.Contains("-release")) - { - DoRelease(novpath); - } - } - else - { - DoRelease(novpath); - } - } - - public static void DoRelease(string novpath) - { - string infopath = novpath + @"\\config\\info.ini"; - string currbranch = GetBranch(infopath); - TurnOnInitialSequence(infopath); - - string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\\releaseversion.txt"; - Console.WriteLine("Creating " + path); - if (!File.Exists(path)) - { - // Create a file to write to. - using (StreamWriter sw = File.CreateText(path)) - { - sw.Write(currbranch); - } - } - Console.WriteLine("Created " + path); - } - - public static void FixedFileCopy(string src, string dest, bool overwrite) - { - if (File.Exists(dest)) - { - File.SetAttributes(dest, FileAttributes.Normal); - } - - File.Copy(src, dest, overwrite); - File.SetAttributes(dest, FileAttributes.Normal); - } - - public static void FixedFileDelete(string src) - { - if (File.Exists(src)) - { - File.SetAttributes(src, FileAttributes.Normal); - File.Delete(src); - } - } - - public static string GetBranch(string infopath) - { - INIFile ini = new INIFile(infopath); - return GetBranch(ini, infopath); - } - - public static string GetBranch(INIFile ini, string infopath) - { - //READ - string versionbranch, extendedVersionNumber, extendedVersionTemplate, extendedVersionRevision, isLite; - string section = "ProgramInfo"; - versionbranch = ini.IniReadValue(section, "Branch", "0.0"); - extendedVersionNumber = ini.IniReadValue(section, "ExtendedVersionNumber", "False"); - extendedVersionTemplate = ini.IniReadValue(section, "ExtendedVersionTemplate", "%version%"); - extendedVersionRevision = ini.IniReadValue(section, "ExtendedVersionRevision", "-1"); - isLite = ini.IniReadValue(section, "IsLite", "False"); - - string novpath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\\Novetus\\bin\\Novetus.exe"; - - if (!extendedVersionNumber.Equals("False")) - { - var versionInfo = FileVersionInfo.GetVersionInfo(novpath); - return extendedVersionTemplate.Replace("%version%", versionbranch) - .Replace("%build%", versionInfo.ProductBuildPart.ToString()) - .Replace("%revision%", versionInfo.FilePrivatePart.ToString()) - .Replace("%extended-revision%", (!extendedVersionRevision.Equals("-1") ? extendedVersionRevision : "")) - .Replace("%lite%", (!isLite.Equals("False") ? " (Lite)" : "")); - } - else - { - return versionbranch; - } - } - - public static void SetToLite(string infopath) - { - INIFile ini = new INIFile(infopath); - string section = "ProgramInfo"; - string isLite = ini.IniReadValue(section, "IsLite", "False"); - - try - { - if (!isLite.Equals("True")) - { - ini.IniWriteValue(section, "IsLite", "True"); - } - } - catch (Exception) - { - SetToLite(infopath); - } - } - - public static void TurnOnInitialSequence(string infopath) - { - //READ - INIFile ini = new INIFile(infopath); - string section = "ProgramInfo"; - - string initialBootup = ini.IniReadValue(section, "InitialBootup", "True"); - if (Convert.ToBoolean(initialBootup) == false) - { - ini.IniWriteValue(section, "InitialBootup", "True"); - } - } - } - #endregion -} diff --git a/Novetus/Novetus.ReleasePreparer/Resources/NovetusIcon.ico b/Novetus/Novetus.ReleasePreparer/Resources/NovetusIcon.ico deleted file mode 100644 index 8cd1cbe06cb36d095d96e779d231450933909936..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 135503 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 - - diff --git a/Novetus/Novetus.Tools.sln b/Novetus/Novetus.Tools.sln deleted file mode 100644 index f90a1a5..0000000 --- a/Novetus/Novetus.Tools.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32630.192 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.Internal.ReleasePreparer", "Novetus.ReleasePreparer\Novetus.Internal.ReleasePreparer.csproj", "{64A99062-3C1C-4D2E-99E4-D6D92443AC98}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novetus.ClientScriptTester", "Novetus.ClientScriptTester\Novetus.ClientScriptTester.csproj", "{83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Debug|Any CPU.Build.0 = Debug|Any CPU - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Release|Any CPU.ActiveCfg = Release|Any CPU - {64A99062-3C1C-4D2E-99E4-D6D92443AC98}.Release|Any CPU.Build.0 = Release|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {83B08607-65B8-4F9C-8D0F-AB1C8EEFFAE0}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {66CA6CE5-670E-48AA-A2DA-9347371D4CA0} - EndGlobalSection -EndGlobal diff --git a/Novetus/NovetusCore/Classes/IDiscordRPC.cs b/Novetus/NovetusCore/Classes/IDiscordRPC.cs index afda33f..e3e7ece 100644 --- a/Novetus/NovetusCore/Classes/IDiscordRPC.cs +++ b/Novetus/NovetusCore/Classes/IDiscordRPC.cs @@ -6,7 +6,8 @@ namespace Novetus.Core { #region Discord RPC //code by discord obv. just renamed it to fit better. - public class DiscordRPC + //TODO: add proper c# implementation. + public class IDiscordRPC { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void ReadyCallback(); @@ -95,5 +96,57 @@ namespace Novetus.Core [DllImport("discord-rpc", EntryPoint = "Discord_Respond", CallingConvention = CallingConvention.Cdecl)] public static extern void Respond(string userId, Reply reply); } - #endregion + + public class DiscordRPC + { + public static void ReadyCallback() + { + Util.ConsolePrint("Discord RPC: Ready", 3); + } + + public static void DisconnectedCallback(int errorCode, string message) + { + Util.ConsolePrint("Discord RPC: Disconnected. Reason - " + errorCode + ": " + message, 2); + } + + public static void ErrorCallback(int errorCode, string message) + { + Util.ConsolePrint("Discord RPC: Error. Reason - " + errorCode + ": " + message, 2); + } + + public static void JoinCallback(string secret) + { + } + + public static void SpectateCallback(string secret) + { + } + + public static void RequestCallback(IDiscordRPC.JoinRequest request) + { + } + + public static void StartDiscord() + { + if (GlobalVars.UserConfiguration.DiscordPresence) + { + GlobalVars.handlers = new IDiscordRPC.EventHandlers(); + GlobalVars.handlers.readyCallback = ReadyCallback; + GlobalVars.handlers.disconnectedCallback += DisconnectedCallback; + GlobalVars.handlers.errorCallback += ErrorCallback; + GlobalVars.handlers.joinCallback += JoinCallback; + GlobalVars.handlers.spectateCallback += SpectateCallback; + GlobalVars.handlers.requestCallback += RequestCallback; + IDiscordRPC.Initialize(GlobalVars.appid, ref GlobalVars.handlers, true, ""); + Util.ConsolePrint("Discord RPC: Initalized", 3); + +#if URI + ClientManagement.UpdateRichPresence(GlobalVars.LauncherState.LoadingURI, true); +#else + ClientManagement.UpdateRichPresence(ClientManagement.GetStateForType(GlobalVars.GameOpened), true); +#endif + } + } + } +#endregion } diff --git a/Novetus/NovetusCore/NovetusCore.projitems b/Novetus/NovetusCore/NovetusCore.projitems index 658dacc..660bc3b 100644 --- a/Novetus/NovetusCore/NovetusCore.projitems +++ b/Novetus/NovetusCore/NovetusCore.projitems @@ -24,6 +24,9 @@ + + + diff --git a/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs b/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs index cad8171..3965103 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs @@ -6,9 +6,9 @@ using System.Globalization; using System.IO; using System.Linq; using System.Text; -using System.Windows.Forms; using System.Xml.Linq; using System.Security.Cryptography; +using System.Windows.Forms; using System.Reflection; #endregion @@ -198,24 +198,24 @@ namespace Novetus.Core DefaultClientInfo.Description = desc; string[] lines = { - SecurityFuncs.Base64Encode(DefaultClientInfo.UsesPlayerName.ToString()), - SecurityFuncs.Base64Encode(DefaultClientInfo.UsesID.ToString()), - SecurityFuncs.Base64Encode(DefaultClientInfo.Warning.ToString()), - SecurityFuncs.Base64Encode(DefaultClientInfo.LegacyMode.ToString()), - SecurityFuncs.Base64Encode(DefaultClientInfo.ClientMD5.ToString()), - SecurityFuncs.Base64Encode(DefaultClientInfo.ScriptMD5.ToString()), - SecurityFuncs.Base64Encode(DefaultClientInfo.Description.ToString()), - SecurityFuncs.Base64Encode(placeholder.ToString()), - SecurityFuncs.Base64Encode(DefaultClientInfo.Fix2007.ToString()), - SecurityFuncs.Base64Encode(DefaultClientInfo.AlreadyHasSecurity.ToString()), - SecurityFuncs.Base64Encode(((int)DefaultClientInfo.ClientLoadOptions).ToString()), - SecurityFuncs.Base64Encode(DefaultClientInfo.SeperateFolders.ToString()), - SecurityFuncs.Base64Encode(DefaultClientInfo.UsesCustomClientEXEName.ToString()), - SecurityFuncs.Base64Encode(DefaultClientInfo.CustomClientEXEName.ToString().Replace("\\", "")), - SecurityFuncs.Base64Encode(DefaultClientInfo.CommandLineArgs.ToString()) + SecurityFuncs.Encode(DefaultClientInfo.UsesPlayerName.ToString()), + SecurityFuncs.Encode(DefaultClientInfo.UsesID.ToString()), + SecurityFuncs.Encode(DefaultClientInfo.Warning.ToString()), + SecurityFuncs.Encode(DefaultClientInfo.LegacyMode.ToString()), + SecurityFuncs.Encode(DefaultClientInfo.ClientMD5.ToString()), + SecurityFuncs.Encode(DefaultClientInfo.ScriptMD5.ToString()), + SecurityFuncs.Encode(DefaultClientInfo.Description.ToString()), + SecurityFuncs.Encode(placeholder.ToString()), + SecurityFuncs.Encode(DefaultClientInfo.Fix2007.ToString()), + SecurityFuncs.Encode(DefaultClientInfo.AlreadyHasSecurity.ToString()), + SecurityFuncs.Encode(((int)DefaultClientInfo.ClientLoadOptions).ToString()), + SecurityFuncs.Encode(DefaultClientInfo.SeperateFolders.ToString()), + SecurityFuncs.Encode(DefaultClientInfo.UsesCustomClientEXEName.ToString()), + SecurityFuncs.Encode(DefaultClientInfo.CustomClientEXEName.ToString().Replace("\\", "")), + SecurityFuncs.Encode(DefaultClientInfo.CommandLineArgs.ToString()) }; - File.WriteAllText(path + "\\clientinfo.nov", SecurityFuncs.Base64Encode(string.Join("|", lines))); + File.WriteAllText(path + "\\clientinfo.nov", SecurityFuncs.Encode(string.Join("|", lines))); } //NOT FOR SDK. @@ -260,36 +260,36 @@ namespace Novetus.Core file = reader.ReadLine(); } - string ConvertedLine = SecurityFuncs.Base64Decode(file); + string ConvertedLine = SecurityFuncs.Decode(file); string[] result = ConvertedLine.Split('|'); - usesplayername = SecurityFuncs.Base64Decode(result[0]); - usesid = SecurityFuncs.Base64Decode(result[1]); - warning = SecurityFuncs.Base64Decode(result[2]); - legacymode = SecurityFuncs.Base64Decode(result[3]); - clientmd5 = SecurityFuncs.Base64Decode(result[4]); - scriptmd5 = SecurityFuncs.Base64Decode(result[5]); - desc = SecurityFuncs.Base64Decode(result[6]); - fix2007 = SecurityFuncs.Base64Decode(result[8]); - alreadyhassecurity = SecurityFuncs.Base64Decode(result[9]); - clientloadoptions = SecurityFuncs.Base64Decode(result[10]); + usesplayername = SecurityFuncs.Decode(result[0]); + usesid = SecurityFuncs.Decode(result[1]); + warning = SecurityFuncs.Decode(result[2]); + legacymode = SecurityFuncs.Decode(result[3]); + clientmd5 = SecurityFuncs.Decode(result[4]); + scriptmd5 = SecurityFuncs.Decode(result[5]); + desc = SecurityFuncs.Decode(result[6]); + fix2007 = SecurityFuncs.Decode(result[8]); + alreadyhassecurity = SecurityFuncs.Decode(result[9]); + clientloadoptions = SecurityFuncs.Decode(result[10]); folders = "False"; usescustomname = "False"; customname = ""; try { - commandlineargs = SecurityFuncs.Base64Decode(result[11]); + commandlineargs = SecurityFuncs.Decode(result[11]); bool parsedValue; if (bool.TryParse(commandlineargs, out parsedValue)) { - folders = SecurityFuncs.Base64Decode(result[11]); - commandlineargs = SecurityFuncs.Base64Decode(result[12]); + folders = SecurityFuncs.Decode(result[11]); + commandlineargs = SecurityFuncs.Decode(result[12]); bool parsedValue2; if (bool.TryParse(commandlineargs, out parsedValue2)) { - usescustomname = SecurityFuncs.Base64Decode(result[12]); - customname = SecurityFuncs.Base64Decode(result[13]); - commandlineargs = SecurityFuncs.Base64Decode(result[14]); + usescustomname = SecurityFuncs.Decode(result[12]); + customname = SecurityFuncs.Decode(result[13]); + commandlineargs = SecurityFuncs.Decode(result[14]); } } } @@ -297,7 +297,7 @@ namespace Novetus.Core { //fake this option until we properly apply it. clientloadoptions = "2"; - commandlineargs = SecurityFuncs.Base64Decode(result[10]); + commandlineargs = SecurityFuncs.Decode(result[10]); } info.UsesPlayerName = Convert.ToBoolean(usesplayername); @@ -365,7 +365,8 @@ namespace Novetus.Core if (initial) { GlobalVars.presence.largeImageKey = GlobalVars.imagekey_large; - GlobalVars.presence.startTimestamp = SecurityFuncs.UnixTimeNow(); + var timeSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)); + GlobalVars.presence.startTimestamp = (long)timeSpan.TotalSeconds; } string ValidMapname = (string.IsNullOrWhiteSpace(mapname) ? "Place1" : mapname); @@ -425,7 +426,7 @@ namespace Novetus.Core break; } - DiscordRPC.UpdatePresence(ref GlobalVars.presence); + IDiscordRPC.UpdatePresence(ref GlobalVars.presence); } } @@ -1046,7 +1047,7 @@ namespace Novetus.Core string fileMD5 = parsedFileParams[1]; string fullFilePath = GlobalPaths.ClientDir + @"\\" + GlobalVars.UserConfiguration.SelectedClient + @"\\" + filePath; - if (!SecurityFuncs.CheckMD5(fileMD5, fullFilePath)) + if (!CheckMD5(fileMD5, fullFilePath)) { #if URI UpdateStatus(label, "The client has been detected as modified."); @@ -1074,10 +1075,90 @@ namespace Novetus.Core } } + public static bool CheckMD5(string MD5Hash, string path) + { + if (!File.Exists(path)) + return false; + + using (var md5 = MD5.Create()) + { + using (var stream = File.OpenRead(path)) + { + byte[] hash = md5.ComputeHash(stream); + string clientMD5 = BitConverter.ToString(hash).Replace("-", ""); + if (clientMD5.Equals(MD5Hash)) + { + return true; + } + else + { + return false; + } + } + } + } + + public static bool checkClientMD5(string client) + { + if (!GlobalVars.AdminMode) + { + if (!GlobalVars.SelectedClientInfo.AlreadyHasSecurity) + { + string rbxexe = ""; + string BasePath = GlobalPaths.BasePath + "\\clients\\" + client; + if (GlobalVars.SelectedClientInfo.LegacyMode) + { + rbxexe = BasePath + "\\RobloxApp.exe"; + } + else if (GlobalVars.SelectedClientInfo.SeperateFolders) + { + rbxexe = BasePath + "\\client\\RobloxApp_client.exe"; + } + else if (GlobalVars.SelectedClientInfo.UsesCustomClientEXEName) + { + rbxexe = BasePath + @"\\" + GlobalVars.SelectedClientInfo.CustomClientEXEName; + } + else + { + rbxexe = BasePath + "\\RobloxApp_client.exe"; + } + return CheckMD5(GlobalVars.SelectedClientInfo.ClientMD5, rbxexe); + } + else + { + return true; + } + } + else + { + return true; + } + } + + public static bool checkScriptMD5(string client) + { + if (!GlobalVars.AdminMode) + { + if (!GlobalVars.SelectedClientInfo.AlreadyHasSecurity) + { + string rbxscript = GlobalPaths.BasePath + "\\clients\\" + client + "\\content\\scripts\\" + GlobalPaths.ScriptName + ".lua"; + return CheckMD5(GlobalVars.SelectedClientInfo.ScriptMD5, rbxscript); + } + else + { + return true; + } + } + else + { + return true; + } + } + #if URI public static void LaunchRBXClient(string ClientName, ScriptType type, bool no3d, bool nomap, EventHandler e, Label label) #else - public static void LaunchRBXClient(string ClientName, ScriptType type, bool no3d, bool nomap, EventHandler e) + public static void LaunchRBXClient(string ClientName, ScriptType type, bool no3d, bool nomap, EventHandler e) #endif { #if LAUNCHER @@ -1271,7 +1352,7 @@ namespace Novetus.Core { if (info.AlreadyHasSecurity != true) { - if (SecurityFuncs.checkClientMD5(ClientName) && SecurityFuncs.checkScriptMD5(ClientName)) + if (checkClientMD5(ClientName) && checkScriptMD5(ClientName)) { OpenClient(type, rbxexe, args, ClientName, mapname, e); } @@ -1755,6 +1836,13 @@ namespace Novetus.Core } } + public static string CopyMapToRBXAsset() + { + string clientcontentpath = GlobalPaths.ClientDir + @"\\" + GlobalVars.UserConfiguration.SelectedClient + @"\\content\\temp.rbxl"; + Util.FixedFileCopy(GlobalVars.UserConfiguration.MapPath, clientcontentpath, true); + return GlobalPaths.AltBaseGameDir + "temp.rbxl"; + } + public static string CompileScript(string code, string tag, string endtag, string mapfile, string luafile, string rbxexe, bool usesharedtags = true) { return CompileScript(GlobalVars.UserConfiguration.SelectedClient, code, tag, endtag, mapfile, luafile, rbxexe, usesharedtags); @@ -1823,7 +1911,7 @@ namespace Novetus.Core string extractedCode = GetArgsFromTag(code, start, end); #if LAUNCHER - string md5dir = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(Assembly.GetExecutingAssembly().Location) : ""; + string md5dir = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(Assembly.GetExecutingAssembly().Location) : ""; #else string md5dir = !info.AlreadyHasSecurity ? SecurityFuncs.GenerateMD5(GlobalPaths.RootPathLauncher + "\\Novetus.exe") : ""; #endif @@ -1878,7 +1966,7 @@ namespace Novetus.Core .Replace("%extrad%", GlobalPaths.extraGameDir + GlobalVars.UserCustomization.Extra) .Replace("%hat4d%", GlobalPaths.hatGameDir + GlobalVars.UserCustomization.Extra) .Replace("%mapfiled%", GlobalPaths.BaseGameDir + GlobalVars.UserConfiguration.MapPathSnip.Replace(@"\\", @"\").Replace(@"/", @"\")) - .Replace("%mapfilec%", extractedCode.Contains("%mapfilec%") ? NovetusFuncs.CopyMapToRBXAsset() : "") + .Replace("%mapfilec%", extractedCode.Contains("%mapfilec%") ? CopyMapToRBXAsset() : "") .Replace("%tripcode%", GlobalVars.PlayerTripcode) .Replace("%scripttype%", Generator.GetNameForType(type)) .Replace("%notifications%", GlobalVars.UserConfiguration.ShowServerNotifications.ToString().ToLower()) diff --git a/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs b/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs index 14ae392..af0bb27 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs @@ -11,7 +11,8 @@ using System.Drawing.Imaging; using System.Text.RegularExpressions; using System.Windows.Forms; using System.Xml.Serialization; -using System.Runtime.Versioning; +using System.Xml; +using System.Xml.Linq; #endregion namespace Novetus.Core @@ -971,7 +972,8 @@ namespace Novetus.Core if (!forcewrite) { - string curval = NovetusFuncs.GenerateAndReturnTripcode(); + //Powered by https://github.com/davcs86/csharp-uhwid + string curval = UHWIDEngine.AdvancedUid; if (!GlobalVars.PlayerTripcode.Equals(curval)) { GlobalVars.PlayerTripcode = curval; @@ -1360,6 +1362,101 @@ namespace Novetus.Core GlobalVars.UserCustomization = new FileFormat.CustomizationConfig(); ReloadLoadoutValue(); } + public static string GetItemTextureLocalPath(string item, string nameprefix) + { + //don't bother, we're offline. + if (GlobalVars.ExternalIP.Equals("localhost")) + return ""; + + if (!GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%localizeonlineclothing%")) + return ""; + + if (item.Contains("http://") || item.Contains("https://")) + { + string peram = "id="; + string fullname = nameprefix + "Temp.png"; + + if (item.Contains(peram)) + { + string id = item.After(peram); + fullname = id + ".png"; + } + else + { + return item; + } + + Downloader download = new Downloader(item, fullname, "", GlobalPaths.AssetCacheDirAssets); + + try + { + string path = download.GetFullDLPath(); + download.InitDownloadNoDialog(path); + return GlobalPaths.AssetCacheAssetsGameDir + download.fileName; + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); +#else + catch (Exception) + { +#endif + } + } + + return ""; + } + + public static string GetItemTextureID(string item, string name, AssetCacheDefBasic assetCacheDef) + { + //don't bother, we're offline. + if (GlobalVars.ExternalIP.Equals("localhost")) + return ""; + + if (!GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%localizeonlineclothing%")) + return ""; + + if (item.Contains("http://") || item.Contains("https://")) + { + string peram = "id="; + if (!item.Contains(peram)) + { + return item; + } + + Downloader download = new Downloader(item, name + "Temp.rbxm", "", GlobalPaths.AssetCacheDirAssets); + + try + { + string path = download.GetFullDLPath(); + download.InitDownloadNoDialog(path); + string oldfile = File.ReadAllText(path); + string fixedfile = RobloxXML.RemoveInvalidXmlChars(RobloxXML.ReplaceHexadecimalSymbols(oldfile)).Replace(" ", "\t").Replace("#9;", "\t"); + XDocument doc = null; + XmlReaderSettings xmlReaderSettings = new XmlReaderSettings { CheckCharacters = false }; + Stream filestream = Util.GenerateStreamFromString(fixedfile); + using (XmlReader xmlReader = XmlReader.Create(filestream, xmlReaderSettings)) + { + xmlReader.MoveToContent(); + doc = XDocument.Load(xmlReader); + } + + return RobloxXML.GetURLInNodes(doc, assetCacheDef.Class, assetCacheDef.Id[0], item); + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); +#else + catch (Exception) + { +#endif + } + } + + return ""; + } public static void ReloadLoadoutValue(bool localizeOnlineClothing = false) { @@ -1404,15 +1501,15 @@ namespace Novetus.Core if (localizeOnlineClothing) { - GlobalVars.TShirtTextureID = NovetusFuncs.GetItemTextureID(GlobalVars.UserCustomization.TShirt, "TShirt", new AssetCacheDefBasic("ShirtGraphic", new string[] { "Graphic" })); - GlobalVars.ShirtTextureID = NovetusFuncs.GetItemTextureID(GlobalVars.UserCustomization.Shirt, "Shirt", new AssetCacheDefBasic("Shirt", new string[] { "ShirtTemplate" })); - GlobalVars.PantsTextureID = NovetusFuncs.GetItemTextureID(GlobalVars.UserCustomization.Pants, "Pants", new AssetCacheDefBasic("Pants", new string[] { "PantsTemplate" })); - GlobalVars.FaceTextureID = NovetusFuncs.GetItemTextureID(GlobalVars.UserCustomization.Face, "Face", new AssetCacheDefBasic("Decal", new string[] { "Texture" })); + GlobalVars.TShirtTextureID = GetItemTextureID(GlobalVars.UserCustomization.TShirt, "TShirt", new AssetCacheDefBasic("ShirtGraphic", new string[] { "Graphic" })); + GlobalVars.ShirtTextureID = GetItemTextureID(GlobalVars.UserCustomization.Shirt, "Shirt", new AssetCacheDefBasic("Shirt", new string[] { "ShirtTemplate" })); + GlobalVars.PantsTextureID = GetItemTextureID(GlobalVars.UserCustomization.Pants, "Pants", new AssetCacheDefBasic("Pants", new string[] { "PantsTemplate" })); + GlobalVars.FaceTextureID = GetItemTextureID(GlobalVars.UserCustomization.Face, "Face", new AssetCacheDefBasic("Decal", new string[] { "Texture" })); - GlobalVars.TShirtTextureLocal = NovetusFuncs.GetItemTextureLocalPath(GlobalVars.TShirtTextureID, "TShirt"); - GlobalVars.ShirtTextureLocal = NovetusFuncs.GetItemTextureLocalPath(GlobalVars.ShirtTextureID, "Shirt"); - GlobalVars.PantsTextureLocal = NovetusFuncs.GetItemTextureLocalPath(GlobalVars.PantsTextureID, "Pants"); - GlobalVars.FaceTextureLocal = NovetusFuncs.GetItemTextureLocalPath(GlobalVars.FaceTextureID, "Face"); + GlobalVars.TShirtTextureLocal = GetItemTextureLocalPath(GlobalVars.TShirtTextureID, "TShirt"); + GlobalVars.ShirtTextureLocal = GetItemTextureLocalPath(GlobalVars.ShirtTextureID, "Shirt"); + GlobalVars.PantsTextureLocal = GetItemTextureLocalPath(GlobalVars.PantsTextureID, "Pants"); + GlobalVars.FaceTextureLocal = GetItemTextureLocalPath(GlobalVars.FaceTextureID, "Face"); } } diff --git a/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs b/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs index 8465a11..0908ede 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/GlobalVars.cs @@ -81,7 +81,7 @@ namespace Novetus.Core LoadingURI = 6 } - public static DiscordRPC.EventHandlers handlers; + public static IDiscordRPC.EventHandlers handlers; #endregion #region Class definitions @@ -97,7 +97,7 @@ namespace Novetus.Core public static string DefaultIP = "localhost"; public static int DefaultRobloxPort = 53640; public static GameServer CurrentServer = new GameServer(DefaultIP, DefaultRobloxPort); - public static string ExternalIP = SecurityFuncs.GetExternalIPAddress(); + public static string ExternalIP = NovetusFuncs.GetExternalIPAddress(); public static ScriptType GameOpened = ScriptType.None; public static string PlayerTripcode = ""; #if LAUNCHER || URI @@ -127,7 +127,7 @@ namespace Novetus.Core #region Discord Variables //discord - public static DiscordRPC.RichPresence presence; + public static IDiscordRPC.RichPresence presence; public static string appid = "505955125727330324"; public static string imagekey_large = "novetus_large"; public static string image_ingame = "ingame_small"; diff --git a/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs b/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs index f27dc3c..125240a 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/NetFuncs.cs @@ -10,15 +10,40 @@ using Titanium.Web.Proxy.Models; namespace Novetus.Core { #region NetFuncs - public static class NetFuncs { - public static void InitUPnP(EventHandler DeviceFound, EventHandler DeviceLost) + public static void InitUPnP() { if (GlobalVars.UserConfiguration.UPnP) { - NatUtility.DeviceFound += DeviceFound; - NatUtility.StartDiscovery(); + try + { + NatUtility.DeviceFound += DeviceFound; + NatUtility.StartDiscovery(); + Util.ConsolePrint("UPnP: Service initialized", 3); + } + catch (Exception ex) + { + Util.LogExceptions(ex); + Util.ConsolePrint("UPnP: Unable to initialize UPnP. Reason - " + ex.Message, 2); + } + } + } + + public static void DeviceFound(object sender, DeviceEventArgs args) + { + try + { + INatDevice device = args.Device; + string IP = !string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : device.GetExternalIP().ToString(); + Util.ConsolePrint("UPnP: Device '" + IP + "' registered.", 3); + StartUPnP(device, Protocol.Udp, GlobalVars.UserConfiguration.RobloxPort); + StartUPnP(device, Protocol.Tcp, GlobalVars.UserConfiguration.RobloxPort); + } + catch (Exception ex) + { + Util.LogExceptions(ex); + Util.ConsolePrint("UPnP: Unable to register device. Reason - " + ex.Message, 2); } } @@ -26,14 +51,25 @@ namespace Novetus.Core { if (GlobalVars.UserConfiguration.UPnP) { - Mapping checker = device.GetSpecificMapping(protocol, port); - int mapPublic = checker.PublicPort; - int mapPrivate = checker.PrivatePort; - - if (mapPublic == -1 && mapPrivate == -1) + try { - Mapping portmap = new Mapping(protocol, port, port); - device.CreatePortMap(portmap); + Mapping checker = device.GetSpecificMapping(protocol, port); + int mapPublic = checker.PublicPort; + int mapPrivate = checker.PrivatePort; + + if (mapPublic == -1 && mapPrivate == -1) + { + Mapping portmap = new Mapping(protocol, port, port); + device.CreatePortMap(portmap); + } + + string IP = !string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : device.GetExternalIP().ToString(); + Util.ConsolePrint("UPnP: Port " + port + " opened on '" + IP + "' (" + protocol.ToString() + ")", 3); + } + catch (Exception ex) + { + Util.LogExceptions(ex); + Util.ConsolePrint("UPnP: Unable to open port mapping. Reason - " + ex.Message, 2); } } } @@ -42,14 +78,25 @@ namespace Novetus.Core { if (GlobalVars.UserConfiguration.UPnP) { - Mapping checker = device.GetSpecificMapping(protocol, port); - int mapPublic = checker.PublicPort; - int mapPrivate = checker.PrivatePort; - - if (mapPublic != -1 && mapPrivate != -1) + try { - Mapping portmap = new Mapping(protocol, port, port); - device.DeletePortMap(portmap); + Mapping checker = device.GetSpecificMapping(protocol, port); + int mapPublic = checker.PublicPort; + int mapPrivate = checker.PrivatePort; + + if (mapPublic != -1 && mapPrivate != -1) + { + Mapping portmap = new Mapping(protocol, port, port); + device.DeletePortMap(portmap); + } + + string IP = !string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : device.GetExternalIP().ToString(); + Util.ConsolePrint("UPnP: Port " + port + " closed on '" + IP + "' (" + protocol.ToString() + ")", 3); + } + catch (Exception ex) + { + Util.LogExceptions(ex); + Util.ConsolePrint("UPnP: Unable to close port mapping. Reason - " + ex.Message, 2); } } } diff --git a/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs b/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs index dd5bb2e..baec1b7 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs @@ -1,13 +1,10 @@ #region Usings using System; -using System.IO; using System.Text.RegularExpressions; using System.Threading.Tasks; -using System.Xml; -using System.Xml.Linq; using System.Linq; using System.Windows.Forms; -using System.Collections.Generic; +using System.Net; #endregion namespace Novetus.Core @@ -15,127 +12,69 @@ namespace Novetus.Core #region Novetus Functions public class NovetusFuncs { - public static string CopyMapToRBXAsset() + public static int GenerateRandomNumber() { - string clientcontentpath = GlobalPaths.ClientDir + @"\\" + GlobalVars.UserConfiguration.SelectedClient + @"\\content\\temp.rbxl"; - Util.FixedFileCopy(GlobalVars.UserConfiguration.MapPath, clientcontentpath, true); - return GlobalPaths.AltBaseGameDir + "temp.rbxl"; - } + CryptoRandom random = new CryptoRandom(); + int randomID = 0; + int randIDmode = random.Next(0, 8); + int idlimit = 0; - public static string GetItemTextureLocalPath(string item, string nameprefix) - { - //don't bother, we're offline. - if (GlobalVars.ExternalIP.Equals("localhost")) - return ""; - - if (!GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%localizeonlineclothing%")) - return ""; - - if (item.Contains("http://") || item.Contains("https://")) + switch (randIDmode) { - string peram = "id="; - string fullname = nameprefix + "Temp.png"; - - if (item.Contains(peram)) - { - string id = item.After(peram); - fullname = id + ".png"; - } - else - { - return item; - } - - Downloader download = new Downloader(item, fullname, "", GlobalPaths.AssetCacheDirAssets); - - try - { - string path = download.GetFullDLPath(); - download.InitDownloadNoDialog(path); - return GlobalPaths.AssetCacheAssetsGameDir + download.fileName; - } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif - } + case 0: + idlimit = 9; + break; + case 1: + idlimit = 99; + break; + case 2: + idlimit = 999; + break; + case 3: + idlimit = 9999; + break; + case 4: + idlimit = 99999; + break; + case 5: + idlimit = 999999; + break; + case 6: + idlimit = 9999999; + break; + case 7: + idlimit = 99999999; + break; + case 8: + default: + break; } - return ""; - } - - public static string GetItemTextureID(string item, string name, AssetCacheDefBasic assetCacheDef) - { - //don't bother, we're offline. - if (GlobalVars.ExternalIP.Equals("localhost")) - return ""; - - if (!GlobalVars.SelectedClientInfo.CommandLineArgs.Contains("%localizeonlineclothing%")) - return ""; - - if (item.Contains("http://") || item.Contains("https://")) + if (idlimit > 0) { - string peram = "id="; - if (!item.Contains(peram)) - { - return item; - } - - Downloader download = new Downloader(item, name + "Temp.rbxm", "", GlobalPaths.AssetCacheDirAssets); - - try - { - string path = download.GetFullDLPath(); - download.InitDownloadNoDialog(path); - string oldfile = File.ReadAllText(path); - string fixedfile = RobloxXML.RemoveInvalidXmlChars(RobloxXML.ReplaceHexadecimalSymbols(oldfile)).Replace(" ", "\t").Replace("#9;", "\t"); - XDocument doc = null; - XmlReaderSettings xmlReaderSettings = new XmlReaderSettings { CheckCharacters = false }; - Stream filestream = Util.GenerateStreamFromString(fixedfile); - using (XmlReader xmlReader = XmlReader.Create(filestream, xmlReaderSettings)) - { - xmlReader.MoveToContent(); - doc = XDocument.Load(xmlReader); - } - - return RobloxXML.GetURLInNodes(doc, assetCacheDef.Class, assetCacheDef.Id[0], item); - } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif - } + randomID = random.Next(0, idlimit); + } + else + { + randomID = random.Next(); } - return ""; + //2147483647 is max id. + return randomID; } public static void GeneratePlayerID() { - int randomID = SecurityFuncs.GenerateRandomNumber(); + int randomID = GenerateRandomNumber(); //2147483647 is max id. GlobalVars.UserConfiguration.UserID = randomID; } - public static string GenerateAndReturnTripcode() - { - //Powered by https://github.com/davcs86/csharp-uhwid - return UHWIDEngine.AdvancedUid; - } - public static void PingMasterServer(bool online, string reason) { if (online) { - GlobalVars.ServerID = SecurityFuncs.RandomString(30) + SecurityFuncs.GenerateRandomNumber(); + GlobalVars.ServerID = RandomString(30) + GenerateRandomNumber(); GlobalVars.PingURL = "http://" + GlobalVars.UserConfiguration.ServerBrowserServerAddress + "/list.php?name=" + GlobalVars.UserConfiguration.ServerBrowserServerName + "&ip=" + (!string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : GlobalVars.ExternalIP) + @@ -152,45 +91,42 @@ namespace Novetus.Core } Util.ConsolePrint("Pinging master server. " + reason, 4); - Task.Factory.StartNew(() => TryPing()); - } + Task.Factory.StartNew(() => { + string response = Util.HttpGet(GlobalVars.PingURL); - private static void TryPing() - { - string response = Util.HttpGet(GlobalVars.PingURL); - - if (!string.IsNullOrWhiteSpace(response)) - { - Util.ConsolePrint(response, response.Contains("ERROR:") ? 2 : 4); - - if (response.Contains("ERROR:")) + if (!string.IsNullOrWhiteSpace(response)) { - GlobalVars.ServerID = "N/A"; + Util.ConsolePrint(response, response.Contains("ERROR:") ? 2 : 4); + + if (response.Contains("ERROR:")) + { + GlobalVars.ServerID = "N/A"; + } } - } - if (!GlobalVars.ServerID.Equals("N/A")) - { - Util.ConsolePrint("Master server ping successful. Your server's ID is " + GlobalVars.ServerID, 4); - } + if (!GlobalVars.ServerID.Equals("N/A")) + { + Util.ConsolePrint("Master server ping successful. Your server's ID is " + GlobalVars.ServerID, 4); + } - GlobalVars.PingURL = ""; + GlobalVars.PingURL = ""; + }); } public static string[] LoadServerInformation() { string[] lines1 = { - SecurityFuncs.Base64Encode(!string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : GlobalVars.ExternalIP), - SecurityFuncs.Base64Encode(GlobalVars.UserConfiguration.RobloxPort.ToString()), - SecurityFuncs.Base64Encode(GlobalVars.UserConfiguration.SelectedClient) + SecurityFuncs.Encode(!string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : GlobalVars.ExternalIP), + SecurityFuncs.Encode(GlobalVars.UserConfiguration.RobloxPort.ToString()), + SecurityFuncs.Encode(GlobalVars.UserConfiguration.SelectedClient) }; - string URI = "novetus://" + SecurityFuncs.Base64Encode(string.Join("|", lines1), true); + string URI = "novetus://" + SecurityFuncs.Encode(string.Join("|", lines1), true); string[] lines2 = { - SecurityFuncs.Base64Encode("localhost"), - SecurityFuncs.Base64Encode(GlobalVars.UserConfiguration.RobloxPort.ToString()), - SecurityFuncs.Base64Encode(GlobalVars.UserConfiguration.SelectedClient) + SecurityFuncs.Encode("localhost"), + SecurityFuncs.Encode(GlobalVars.UserConfiguration.RobloxPort.ToString()), + SecurityFuncs.Encode(GlobalVars.UserConfiguration.SelectedClient) }; - string URI2 = "novetus://" + SecurityFuncs.Base64Encode(string.Join("|", lines2), true); + string URI2 = "novetus://" + SecurityFuncs.Encode(string.Join("|", lines2), true); GameServer server = new GameServer((!string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : GlobalVars.ExternalIP), GlobalVars.UserConfiguration.RobloxPort); string[] text = { @@ -208,16 +144,6 @@ namespace Novetus.Core return text; } - public static void CreateTXT() - { - List text = new List(); - text.AddRange(LoadServerInformation()); - - string txt = GlobalPaths.BasePath + "\\" + GlobalPaths.ServerInfoFileName; - File.WriteAllLines(txt, text); - Util.ConsolePrint("Server Information sent to file " + txt, 4); - } - #if LAUNCHER || URI public static void LaunchCharacterCustomization() { @@ -293,386 +219,33 @@ namespace Novetus.Core return finalUrl; } - public static void SetupAdminPassword() + public static string RandomString(int length = 30, string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz") { CryptoRandom random = new CryptoRandom(); - string Name1 = SecurityFuncs.GenerateName(random.Next(4, 12)); - string Name2 = SecurityFuncs.GenerateName(random.Next(4, 12)); - GlobalVars.Important = Name1 + Name2; - GlobalVars.Important2 = SecurityFuncs.Encipher(GlobalVars.Important, random.Next(2, 13)); + return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray()); + } + + public static string GetExternalIPAddress() + { + string ipAddress; + + try + { + ipAddress = new WebClient().DownloadString("https://ipv4.icanhazip.com/").TrimEnd(); + } +#if URI || LAUNCHER || BASICLAUNCHER + catch (Exception ex) + { + Util.LogExceptions(ex); +#else + catch (Exception) + { +#endif + ipAddress = "localhost"; + } + + return ipAddress; } } #endregion - - #region Roblox Helpers - #region Vector3 - public class Vector3 - { - public double X; - public double Y; - public double Z; - - public Vector3(double aX, double aY, double aZ) - { - X = aX; - Y = aY; - Z = aZ; - } - } - #endregion - - #region Roblox File Types - public enum RobloxFileType - { - //RBXL and RBXM - RBXL, - RBXM, - //Items - Hat, - Head, - Face, - TShirt, - Shirt, - Pants, - Script, - HeadNoCustomMesh - } - #endregion - - #region Asset Cache Definition - public class AssetCacheDefBasic - { - public AssetCacheDefBasic(string clas, string[] id) - { - Class = clas; - Id = id; - } - - public string Class { get; set; } - public string[] Id { get; set; } - } - - public class AssetCacheDef : AssetCacheDefBasic - { - public AssetCacheDef(string clas, string[] id, string[] ext, - string[] dir, string[] gamedir) : base(clas, id) - { - Ext = ext; - Dir = dir; - GameDir = gamedir; - } - - public string[] Ext { get; set; } - public string[] Dir { get; set; } - public string[] GameDir { get; set; } - } - #endregion - - #region Roblox Type Definitions - public struct RobloxDefs - { - //item defs below - public static AssetCacheDef ItemHatFonts - { - get - { - return new AssetCacheDef("SpecialMesh", - new string[] { "MeshId", "TextureId" }, - new string[] { ".mesh", ".png" }, - new string[] { GlobalPaths.hatdirFonts, GlobalPaths.hatdirTextures }, - new string[] { GlobalPaths.hatGameDirFonts, GlobalPaths.hatGameDirTextures }); - } - } - - public static AssetCacheDef ItemHatSound - { - get - { - return new AssetCacheDef("Sound", - new string[] { "SoundId" }, - new string[] { ".wav" }, - new string[] { GlobalPaths.hatdirSounds }, - new string[] { GlobalPaths.hatGameDirSounds }); - } - } - - public static AssetCacheDef ItemHatScript - { - get - { - return new AssetCacheDef("Script", - new string[] { "LinkedSource" }, - new string[] { ".lua" }, - new string[] { GlobalPaths.hatdirScripts }, - new string[] { GlobalPaths.hatGameDirScripts }); - } - } - - public static AssetCacheDef ItemHatLocalScript - { - get - { - return new AssetCacheDef("LocalScript", - new string[] { "LinkedSource" }, - new string[] { ".lua" }, - new string[] { GlobalPaths.hatdirScripts }, - new string[] { GlobalPaths.hatGameDirScripts }); - } - } - - public static AssetCacheDef ItemHeadFonts - { - get - { - return new AssetCacheDef("SpecialMesh", - new string[] { "MeshId", "TextureId" }, - new string[] { ".mesh", ".png" }, - new string[] { GlobalPaths.headdirFonts, GlobalPaths.headdirTextures }, - new string[] { GlobalPaths.headGameDirFonts, GlobalPaths.headGameDirTextures }); - } - } - - public static AssetCacheDef ItemFaceTexture - { - get - { - return new AssetCacheDef("Decal", - new string[] { "Texture" }, - new string[] { ".png" }, - new string[] { GlobalPaths.facedirTextures }, - new string[] { GlobalPaths.faceGameDirTextures }); - } - } - - public static AssetCacheDef ItemShirtTexture - { - get - { - return new AssetCacheDef("Shirt", - new string[] { "ShirtTemplate" }, - new string[] { ".png" }, - new string[] { GlobalPaths.shirtdirTextures }, - new string[] { GlobalPaths.shirtGameDirTextures }); - } - } - - public static AssetCacheDef ItemTShirtTexture - { - get - { - return new AssetCacheDef("ShirtGraphic", - new string[] { "Graphic" }, - new string[] { ".png" }, - new string[] { GlobalPaths.tshirtdirTextures }, - new string[] { GlobalPaths.tshirtGameDirTextures }); - } - } - - public static AssetCacheDef ItemPantsTexture - { - get - { - return new AssetCacheDef("Pants", - new string[] { "PantsTemplate" }, - new string[] { ".png" }, - new string[] { GlobalPaths.pantsdirTextures }, - new string[] { GlobalPaths.pantsGameDirTextures }); - } - } - } - #endregion - - #region XML Types - public enum XMLTypes - { - Token, - Bool, - Float, - String, - Vector2Int16, - Int - } - #endregion - - #region Roblox XML Parser - public static class RobloxXML - { - public static void EditRenderSettings(XDocument doc, string setting, string value, XMLTypes type) - { - var v = from nodes in doc.Descendants("Item") - where nodes.Attribute("class").Value == "RenderSettings" - select nodes; - - foreach (var item in v) - { - var v2 = from nodes in item.Descendants((type != XMLTypes.Vector2Int16 ? type.ToString().ToLower() : "Vector2int16")) - where nodes.Attribute("name").Value == setting - select nodes; - - foreach (var item2 in v2) - { - if (type != XMLTypes.Vector2Int16) - { - item2.Value = value; - } - else - { - string[] vals = value.Split('x'); - - var v3 = from nodes in item2.Descendants("X") - select nodes; - - foreach (var item3 in v3) - { - item3.Value = vals[0]; - } - - var v4 = from nodes in item2.Descendants("Y") - select nodes; - - foreach (var item4 in v4) - { - item4.Value = vals[1]; - } - } - } - } - } - - public static bool IsRenderSettingStringValid(XDocument doc, string setting, XMLTypes type) - { - if (type != XMLTypes.String) - return false; - - var v = from nodes in doc.Descendants("Item") - where nodes.Attribute("class").Value == "RenderSettings" - select nodes; - - foreach (var item in v) - { - var v2 = from nodes in item.Descendants(type.ToString().ToLower()) - where nodes.Attribute("name").Value == setting - select nodes; - - foreach (var item2 in v2) - { - return true; - } - } - - return false; - } - - public static string GetRenderSettings(XDocument doc, string setting, XMLTypes type) - { - var v = from nodes in doc.Descendants("Item") - where nodes.Attribute("class").Value == "RenderSettings" - select nodes; - - foreach (var item in v) - { - var v2 = from nodes in item.Descendants((type != XMLTypes.Vector2Int16 ? type.ToString().ToLower() : "Vector2int16")) - where nodes.Attribute("name").Value == setting - select nodes; - - foreach (var item2 in v2) - { - if (type != XMLTypes.Vector2Int16) - { - return item2.Value; - } - else - { - string ValX = ""; - string ValY = ""; - - var v3 = from nodes in item2.Descendants("X") - select nodes; - - foreach (var item3 in v3) - { - ValX = item3.Value; - } - - var v4 = from nodes in item2.Descendants("Y") - select nodes; - - foreach (var item4 in v4) - { - ValY = item4.Value; - } - - return ValX + "x" + ValY; - } - } - } - - return ""; - } - - public static string GetURLInNodes(XDocument doc, string itemClassValue, string itemIdValue, string url) - { - var v = from nodes in doc.Descendants("Item") - where nodes.Attribute("class").Value == itemClassValue - select nodes; - - foreach (var item in v) - { - var v2 = from nodes in item.Descendants("Content") - where nodes.Attribute("name").Value == itemIdValue - select nodes; - - foreach (var item2 in v2) - { - var v3 = from nodes in item2.Descendants("url") - select nodes; - - foreach (var item3 in v3) - { - if (!item3.Value.Contains("rbxassetid")) - { - if (!item3.Value.Contains("rbxasset")) - { - string oldurl = item3.Value; - string urlFixed = NovetusFuncs.FixURLString(oldurl, url); - string peram = "id="; - - if (urlFixed.Contains(peram)) - { - return urlFixed; - } - } - } - else - { - string oldurl = item3.Value; - string rbxassetid = "rbxassetid://"; - string urlFixed = url + oldurl.After(rbxassetid); - string peram = "id="; - - if (urlFixed.Contains(peram)) - { - return urlFixed; - } - } - } - } - } - - return ""; - } - - public static string RemoveInvalidXmlChars(string content) - { - return new string(content.Where(ch => XmlConvert.IsXmlChar(ch)).ToArray()); - } - - public static string ReplaceHexadecimalSymbols(string txt) - { - string r = "[\x00-\x08\x0B\x0C\x0E-\x1F]"; - return Regex.Replace(txt, r, "", RegexOptions.Compiled); - } - } - #endregion - #endregion } diff --git a/Novetus/NovetusCore/StorageAndFunctions/Roblox Helpers/RobloxTypes.cs b/Novetus/NovetusCore/StorageAndFunctions/Roblox Helpers/RobloxTypes.cs new file mode 100644 index 0000000..30bd82b --- /dev/null +++ b/Novetus/NovetusCore/StorageAndFunctions/Roblox Helpers/RobloxTypes.cs @@ -0,0 +1,163 @@ +namespace Novetus.Core +{ + #region Roblox File Types + public enum RobloxFileType + { + //RBXL and RBXM + RBXL, + RBXM, + //Items + Hat, + Head, + Face, + TShirt, + Shirt, + Pants, + Script, + HeadNoCustomMesh + } + #endregion + + #region Asset Cache Definition + public class AssetCacheDefBasic + { + public AssetCacheDefBasic(string clas, string[] id) + { + Class = clas; + Id = id; + } + + public string Class { get; set; } + public string[] Id { get; set; } + } + + public class AssetCacheDef : AssetCacheDefBasic + { + public AssetCacheDef(string clas, string[] id, string[] ext, + string[] dir, string[] gamedir) : base(clas, id) + { + Ext = ext; + Dir = dir; + GameDir = gamedir; + } + + public string[] Ext { get; set; } + public string[] Dir { get; set; } + public string[] GameDir { get; set; } + } + #endregion + + #region Roblox Type Definitions + public struct RobloxDefs + { + //item defs below + public static AssetCacheDef ItemHatFonts + { + get + { + return new AssetCacheDef("SpecialMesh", + new string[] { "MeshId", "TextureId" }, + new string[] { ".mesh", ".png" }, + new string[] { GlobalPaths.hatdirFonts, GlobalPaths.hatdirTextures }, + new string[] { GlobalPaths.hatGameDirFonts, GlobalPaths.hatGameDirTextures }); + } + } + + public static AssetCacheDef ItemHatSound + { + get + { + return new AssetCacheDef("Sound", + new string[] { "SoundId" }, + new string[] { ".wav" }, + new string[] { GlobalPaths.hatdirSounds }, + new string[] { GlobalPaths.hatGameDirSounds }); + } + } + + public static AssetCacheDef ItemHatScript + { + get + { + return new AssetCacheDef("Script", + new string[] { "LinkedSource" }, + new string[] { ".lua" }, + new string[] { GlobalPaths.hatdirScripts }, + new string[] { GlobalPaths.hatGameDirScripts }); + } + } + + public static AssetCacheDef ItemHatLocalScript + { + get + { + return new AssetCacheDef("LocalScript", + new string[] { "LinkedSource" }, + new string[] { ".lua" }, + new string[] { GlobalPaths.hatdirScripts }, + new string[] { GlobalPaths.hatGameDirScripts }); + } + } + + public static AssetCacheDef ItemHeadFonts + { + get + { + return new AssetCacheDef("SpecialMesh", + new string[] { "MeshId", "TextureId" }, + new string[] { ".mesh", ".png" }, + new string[] { GlobalPaths.headdirFonts, GlobalPaths.headdirTextures }, + new string[] { GlobalPaths.headGameDirFonts, GlobalPaths.headGameDirTextures }); + } + } + + public static AssetCacheDef ItemFaceTexture + { + get + { + return new AssetCacheDef("Decal", + new string[] { "Texture" }, + new string[] { ".png" }, + new string[] { GlobalPaths.facedirTextures }, + new string[] { GlobalPaths.faceGameDirTextures }); + } + } + + public static AssetCacheDef ItemShirtTexture + { + get + { + return new AssetCacheDef("Shirt", + new string[] { "ShirtTemplate" }, + new string[] { ".png" }, + new string[] { GlobalPaths.shirtdirTextures }, + new string[] { GlobalPaths.shirtGameDirTextures }); + } + } + + public static AssetCacheDef ItemTShirtTexture + { + get + { + return new AssetCacheDef("ShirtGraphic", + new string[] { "Graphic" }, + new string[] { ".png" }, + new string[] { GlobalPaths.tshirtdirTextures }, + new string[] { GlobalPaths.tshirtGameDirTextures }); + } + } + + public static AssetCacheDef ItemPantsTexture + { + get + { + return new AssetCacheDef("Pants", + new string[] { "PantsTemplate" }, + new string[] { ".png" }, + new string[] { GlobalPaths.pantsdirTextures }, + new string[] { GlobalPaths.pantsGameDirTextures }); + } + } + } + #endregion +} diff --git a/Novetus/NovetusCore/StorageAndFunctions/Roblox Helpers/RobloxXML.cs b/Novetus/NovetusCore/StorageAndFunctions/Roblox Helpers/RobloxXML.cs new file mode 100644 index 0000000..06e3c6c --- /dev/null +++ b/Novetus/NovetusCore/StorageAndFunctions/Roblox Helpers/RobloxXML.cs @@ -0,0 +1,203 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml; +using System.Xml.Linq; + +namespace Novetus.Core +{ + #region XML Types + public enum XMLTypes + { + Token, + Bool, + Float, + String, + Vector2Int16, + Int + } + #endregion + + #region Roblox XML Parser + public static class RobloxXML + { + public static void EditRenderSettings(XDocument doc, string setting, string value, XMLTypes type) + { + var v = from nodes in doc.Descendants("Item") + where nodes.Attribute("class").Value == "RenderSettings" + select nodes; + + foreach (var item in v) + { + var v2 = from nodes in item.Descendants((type != XMLTypes.Vector2Int16 ? type.ToString().ToLower() : "Vector2int16")) + where nodes.Attribute("name").Value == setting + select nodes; + + foreach (var item2 in v2) + { + if (type != XMLTypes.Vector2Int16) + { + item2.Value = value; + } + else + { + string[] vals = value.Split('x'); + + var v3 = from nodes in item2.Descendants("X") + select nodes; + + foreach (var item3 in v3) + { + item3.Value = vals[0]; + } + + var v4 = from nodes in item2.Descendants("Y") + select nodes; + + foreach (var item4 in v4) + { + item4.Value = vals[1]; + } + } + } + } + } + + public static bool IsRenderSettingStringValid(XDocument doc, string setting, XMLTypes type) + { + if (type != XMLTypes.String) + return false; + + var v = from nodes in doc.Descendants("Item") + where nodes.Attribute("class").Value == "RenderSettings" + select nodes; + + foreach (var item in v) + { + var v2 = from nodes in item.Descendants(type.ToString().ToLower()) + where nodes.Attribute("name").Value == setting + select nodes; + + foreach (var item2 in v2) + { + return true; + } + } + + return false; + } + + public static string GetRenderSettings(XDocument doc, string setting, XMLTypes type) + { + var v = from nodes in doc.Descendants("Item") + where nodes.Attribute("class").Value == "RenderSettings" + select nodes; + + foreach (var item in v) + { + var v2 = from nodes in item.Descendants((type != XMLTypes.Vector2Int16 ? type.ToString().ToLower() : "Vector2int16")) + where nodes.Attribute("name").Value == setting + select nodes; + + foreach (var item2 in v2) + { + if (type != XMLTypes.Vector2Int16) + { + return item2.Value; + } + else + { + string ValX = ""; + string ValY = ""; + + var v3 = from nodes in item2.Descendants("X") + select nodes; + + foreach (var item3 in v3) + { + ValX = item3.Value; + } + + var v4 = from nodes in item2.Descendants("Y") + select nodes; + + foreach (var item4 in v4) + { + ValY = item4.Value; + } + + return ValX + "x" + ValY; + } + } + } + + return ""; + } + + public static string GetURLInNodes(XDocument doc, string itemClassValue, string itemIdValue, string url) + { + var v = from nodes in doc.Descendants("Item") + where nodes.Attribute("class").Value == itemClassValue + select nodes; + + foreach (var item in v) + { + var v2 = from nodes in item.Descendants("Content") + where nodes.Attribute("name").Value == itemIdValue + select nodes; + + foreach (var item2 in v2) + { + var v3 = from nodes in item2.Descendants("url") + select nodes; + + foreach (var item3 in v3) + { + if (!item3.Value.Contains("rbxassetid")) + { + if (!item3.Value.Contains("rbxasset")) + { + string oldurl = item3.Value; + string urlFixed = NovetusFuncs.FixURLString(oldurl, url); + string peram = "id="; + + if (urlFixed.Contains(peram)) + { + return urlFixed; + } + } + } + else + { + string oldurl = item3.Value; + string rbxassetid = "rbxassetid://"; + string urlFixed = url + oldurl.After(rbxassetid); + string peram = "id="; + + if (urlFixed.Contains(peram)) + { + return urlFixed; + } + } + } + } + } + + return ""; + } + + public static string RemoveInvalidXmlChars(string content) + { + return new string(content.Where(ch => XmlConvert.IsXmlChar(ch)).ToArray()); + } + + public static string ReplaceHexadecimalSymbols(string txt) + { + string r = "[\x00-\x08\x0B\x0C\x0E-\x1F]"; + return Regex.Replace(txt, r, "", RegexOptions.Compiled); + } + } + #endregion +} diff --git a/Novetus/NovetusCore/StorageAndFunctions/Roblox Helpers/Vector3.cs b/Novetus/NovetusCore/StorageAndFunctions/Roblox Helpers/Vector3.cs new file mode 100644 index 0000000..1d94c10 --- /dev/null +++ b/Novetus/NovetusCore/StorageAndFunctions/Roblox Helpers/Vector3.cs @@ -0,0 +1,18 @@ +#region Vector3 +namespace Novetus.Core +{ + public class Vector3 + { + public double X; + public double Y; + public double Z; + + public Vector3(double aX, double aY, double aZ) + { + X = aX; + Y = aY; + Z = aZ; + } + } +} +#endregion diff --git a/Novetus/NovetusCore/StorageAndFunctions/SecurityFuncs.cs b/Novetus/NovetusCore/StorageAndFunctions/SecurityFuncs.cs index 7d1772c..09794c3 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/SecurityFuncs.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/SecurityFuncs.cs @@ -21,96 +21,35 @@ namespace Novetus.Core { [DllImport("user32.dll")] static extern int SetWindowText(IntPtr hWnd, string text); + public static bool IsElevated { get { return WindowsIdentity.GetCurrent().Owner.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid); } } - public static string RandomString(int length) + public static string Decode(string EncodedData, bool useOldDecoding = false) { - CryptoRandom random = new CryptoRandom(); - const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; - return new string(Enumerable.Repeat(chars, length) - .Select(s => s[random.Next(s.Length)]).ToArray()); - } - - public static int GenerateRandomNumber() - { - CryptoRandom random = new CryptoRandom(); - int randomID = 0; - int randIDmode = random.Next(0, 8); - int idlimit = 0; - - switch (randIDmode) - { - case 0: - idlimit = 9; - break; - case 1: - idlimit = 99; - break; - case 2: - idlimit = 999; - break; - case 3: - idlimit = 9999; - break; - case 4: - idlimit = 99999; - break; - case 5: - idlimit = 999999; - break; - case 6: - idlimit = 9999999; - break; - case 7: - idlimit = 99999999; - break; - case 8: - default: - break; + if (useOldDecoding) + { + return DecodeOld(EncodedData); } - if (idlimit > 0) - { - randomID = random.Next(0, idlimit); - } - else - { - randomID = random.Next(); - } - - //2147483647 is max id. - return randomID; - } - - //these 2 methods are for the clientinfo creator. - public static string Base64DecodeNew(string base64EncodedData) - { - return base64EncodedData.Decrypt(); - } - - public static string Base64DecodeOld(string base64EncodedData) - { - var base64EncodedBytes = Convert.FromBase64String(base64EncodedData); - return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); - } - - //this is for everything else - public static string Base64Decode(string base64EncodedData) - { try { - string decode = base64EncodedData.Decrypt(); + string decode = EncodedData.Decrypt(); return decode; } catch (Exception) { - var base64EncodedBytes = Convert.FromBase64String(base64EncodedData); - return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); + return DecodeOld(EncodedData); } } - public static string Base64Encode(string plainText, bool oldVer = false) + private static string DecodeOld(string EncodedData) + { + var EncodedBytes = Convert.FromBase64String(EncodedData); + return System.Text.Encoding.UTF8.GetString(EncodedBytes); + } + + public static string Encode(string plainText, bool useOldEncoding = false) { - if (oldVer) + if (useOldEncoding) { var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText); return System.Convert.ToBase64String(plainTextBytes); @@ -121,98 +60,6 @@ namespace Novetus.Core } } - public static bool IsBase64String(string s) - { - s = s.Trim(); - return (s.Length % 4 == 0) && Regex.IsMatch(s, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None); - } - - public static long UnixTimeNow() - { - var timeSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)); - return (long)timeSpan.TotalSeconds; - } - - public static bool checkClientMD5(string client) - { - if (!GlobalVars.AdminMode) - { - if (!GlobalVars.SelectedClientInfo.AlreadyHasSecurity) - { - string rbxexe = ""; - string BasePath = GlobalPaths.BasePath + "\\clients\\" + client; - if (GlobalVars.SelectedClientInfo.LegacyMode) - { - rbxexe = BasePath + "\\RobloxApp.exe"; - } - else if (GlobalVars.SelectedClientInfo.SeperateFolders) - { - rbxexe = BasePath + "\\client\\RobloxApp_client.exe"; - } - else if (GlobalVars.SelectedClientInfo.UsesCustomClientEXEName) - { - rbxexe = BasePath + @"\\" + GlobalVars.SelectedClientInfo.CustomClientEXEName; - } - else - { - rbxexe = BasePath + "\\RobloxApp_client.exe"; - } - return CheckMD5(GlobalVars.SelectedClientInfo.ClientMD5, rbxexe); - } - else - { - return true; - } - } - else - { - return true; - } - } - - public static bool checkScriptMD5(string client) - { - if (!GlobalVars.AdminMode) - { - if (!GlobalVars.SelectedClientInfo.AlreadyHasSecurity) - { - string rbxscript = GlobalPaths.BasePath + "\\clients\\" + client + "\\content\\scripts\\" + GlobalPaths.ScriptName + ".lua"; - return CheckMD5(GlobalVars.SelectedClientInfo.ScriptMD5, rbxscript); - } - else - { - return true; - } - } - else - { - return true; - } - } - - public static bool CheckMD5(string MD5Hash, string path) - { - if (!File.Exists(path)) - return false; - - using (var md5 = MD5.Create()) - { - using (var stream = File.OpenRead(path)) - { - byte[] hash = md5.ComputeHash(stream); - string clientMD5 = BitConverter.ToString(hash).Replace("-", ""); - if (clientMD5.Equals(MD5Hash)) - { - return true; - } - else - { - return false; - } - } - } - } - public static string GenerateMD5(string filename) { using (var md5 = MD5.Create()) @@ -224,18 +71,10 @@ namespace Novetus.Core } } - public static bool IsElevated - { - get - { - return WindowsIdentity.GetCurrent().Owner.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid); - } - } - - public static string RandomStringTitle() + private static string RandomStringTitle() { CryptoRandom random = new CryptoRandom(); - return new String(' ', random.Next(20)); + return NovetusFuncs.RandomString(random.Next(20), " "); } public static void RenameWindow(Process exe, ScriptType type, string clientname, string mapname) @@ -316,51 +155,8 @@ namespace Novetus.Core } } - public static string GetExternalIPAddress() - { - string ipAddress; - - try - { - ipAddress = new WebClient().DownloadString("https://ipv4.icanhazip.com/").TrimEnd(); - } -#if URI || LAUNCHER || BASICLAUNCHER - catch (Exception ex) - { - Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif - ipAddress = "localhost"; - } - - return ipAddress; - } - - //modified from https://stackoverflow.com/questions/14687658/random-name-generator-in-c-sharp - public static string GenerateName(int len) - { - CryptoRandom r = new CryptoRandom(); - string[] consonants = { "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "l", "n", "p", "q", "r", "s", "sh", "zh", "t", "v", "w", "x" }; - string[] vowels = { "a", "e", "i", "o", "u", "ae", "y" }; - string Name = ""; - Name += consonants[r.Next(consonants.Length)].ToUpper(); - Name += vowels[r.Next(vowels.Length)]; - int b = 2; //b tells how many times a new letter has been added. It's 2 right now because the first two letters are already in the name. - while (b < len) - { - Name += consonants[r.Next(consonants.Length)]; - b++; - Name += vowels[r.Next(vowels.Length)]; - b++; - } - - return Name; - } - //https://www.c-sharpcorner.com/article/caesar-cipher-in-c-sharp/ - public static char cipher(char ch, int key) + private static char cipher(char ch, int key) { if (!char.IsLetter(ch)) { diff --git a/Novetus/NovetusCore/StorageAndFunctions/Util.cs b/Novetus/NovetusCore/StorageAndFunctions/Util.cs index 6cce83e..08cccfc 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/Util.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/Util.cs @@ -907,164 +907,6 @@ namespace Novetus.Core } #endif #endregion - -#if !BASICLAUNCHER - #region UPnP - public static void InitUPnP() - { - if (GlobalVars.UserConfiguration.UPnP) - { - try - { - NetFuncs.InitUPnP(DeviceFound, DeviceLost); - ConsolePrint("UPnP: Service initialized", 3); - } - catch (Exception ex) - { - LogExceptions(ex); - ConsolePrint("UPnP: Unable to initialize UPnP. Reason - " + ex.Message, 2); - } - } - } - - public static void StartUPnP(INatDevice device, Protocol protocol, int port) - { - if (GlobalVars.UserConfiguration.UPnP) - { - try - { - NetFuncs.StartUPnP(device, protocol, port); - string IP = !string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : device.GetExternalIP().ToString(); - ConsolePrint("UPnP: Port " + port + " opened on '" + IP + "' (" + protocol.ToString() + ")", 3); - } - catch (Exception ex) - { - LogExceptions(ex); - ConsolePrint("UPnP: Unable to open port mapping. Reason - " + ex.Message, 2); - } - } - } - - public static void StopUPnP(INatDevice device, Protocol protocol, int port) - { - if (GlobalVars.UserConfiguration.UPnP) - { - try - { - NetFuncs.StopUPnP(device, protocol, port); - string IP = !string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : device.GetExternalIP().ToString(); - ConsolePrint("UPnP: Port " + port + " closed on '" + IP + "' (" + protocol.ToString() + ")", 3); - } - catch (Exception ex) - { - LogExceptions(ex); - ConsolePrint("UPnP: Unable to close port mapping. Reason - " + ex.Message, 2); - } - } - } - - public static void DeviceFound(object sender, DeviceEventArgs args) - { - try - { - INatDevice device = args.Device; - string IP = !string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : device.GetExternalIP().ToString(); - ConsolePrint("UPnP: Device '" + IP + "' registered.", 3); - StartUPnP(device, Protocol.Udp, GlobalVars.UserConfiguration.RobloxPort); - StartUPnP(device, Protocol.Tcp, GlobalVars.UserConfiguration.RobloxPort); - } - catch (Exception ex) - { - LogExceptions(ex); - ConsolePrint("UPnP: Unable to register device. Reason - " + ex.Message, 2); - } - } - - public static void DeviceLost(object sender, DeviceEventArgs args) - { - try - { - INatDevice device = args.Device; - string IP = !string.IsNullOrWhiteSpace(GlobalVars.UserConfiguration.AlternateServerIP) ? GlobalVars.UserConfiguration.AlternateServerIP : device.GetExternalIP().ToString(); - ConsolePrint("UPnP: Device '" + IP + "' disconnected.", 3); - StopUPnP(device, Protocol.Udp, GlobalVars.UserConfiguration.RobloxPort); - StopUPnP(device, Protocol.Tcp, GlobalVars.UserConfiguration.RobloxPort); - } - catch (Exception ex) - { - LogExceptions(ex); - ConsolePrint("UPnP: Unable to disconnect device. Reason - " + ex.Message, 2); - } - } - #endregion - - #region Discord - public static void ReadyCallback() - { - ConsolePrint("Discord RPC: Ready", 3); - } - - public static void DisconnectedCallback(int errorCode, string message) - { - ConsolePrint("Discord RPC: Disconnected. Reason - " + errorCode + ": " + message, 2); - } - - public static void ErrorCallback(int errorCode, string message) - { - ConsolePrint("Discord RPC: Error. Reason - " + errorCode + ": " + message, 2); - } - - public static void JoinCallback(string secret) - { - } - - public static void SpectateCallback(string secret) - { - } - - public static void RequestCallback(DiscordRPC.JoinRequest request) - { - } - - public static void StartDiscord() - { - if (GlobalVars.UserConfiguration.DiscordPresence) - { - GlobalVars.handlers = new DiscordRPC.EventHandlers(); - GlobalVars.handlers.readyCallback = ReadyCallback; - GlobalVars.handlers.disconnectedCallback += DisconnectedCallback; - GlobalVars.handlers.errorCallback += ErrorCallback; - GlobalVars.handlers.joinCallback += JoinCallback; - GlobalVars.handlers.spectateCallback += SpectateCallback; - GlobalVars.handlers.requestCallback += RequestCallback; - DiscordRPC.Initialize(GlobalVars.appid, ref GlobalVars.handlers, true, ""); - ConsolePrint("Discord RPC: Initalized", 3); - - ClientManagement.UpdateRichPresence(ClientManagement.GetStateForType(GlobalVars.GameOpened), true); - } - } - #endregion -#endif - } - #endregion - - #region Tab Control without Header - //https://stackoverflow.com/questions/23247941/c-sharp-how-to-remove-tabcontrol-border - - public partial class TabControlWithoutHeader : TabControl - { - public TabControlWithoutHeader() - { - if (!DesignMode) Multiline = true; - } - - protected override void WndProc(ref Message m) - { - if (m.Msg == 0x1328 && !DesignMode) - m.Result = new IntPtr(1); - else - base.WndProc(ref m); - } } #endregion } \ No newline at end of file diff --git a/Novetus/NovetusLauncher/Classes/Launcher/SplashLoader.cs b/Novetus/NovetusLauncher/Classes/Launcher/SplashLoader.cs index f94c366..89e0988 100644 --- a/Novetus/NovetusLauncher/Classes/Launcher/SplashLoader.cs +++ b/Novetus/NovetusLauncher/Classes/Launcher/SplashLoader.cs @@ -157,7 +157,7 @@ public class Splash DateTime now = DateTime.Now; return text.Replace("%name%", GlobalVars.UserConfiguration.PlayerName) - .Replace("%randomtext%", SecurityFuncs.RandomString(random.Next(2, (GlobalVars.UserConfiguration.LauncherStyle == Settings.Style.Stylish ? 64 : 32)))) + .Replace("%randomtext%", NovetusFuncs.RandomString(random.Next(2, (GlobalVars.UserConfiguration.LauncherStyle == Settings.Style.Stylish ? 64 : 32)))) .Replace("%version%", GlobalVars.ProgramInformation.Version) .Replace("%year%", now.Year.ToString()) .Replace("%day%", now.Day.ToString()) diff --git a/Novetus/NovetusLauncher/Classes/TabControlWithoutHeader.cs b/Novetus/NovetusLauncher/Classes/TabControlWithoutHeader.cs new file mode 100644 index 0000000..3810a03 --- /dev/null +++ b/Novetus/NovetusLauncher/Classes/TabControlWithoutHeader.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; + +//https://stackoverflow.com/questions/23247941/c-sharp-how-to-remove-tabcontrol-border + +public partial class TabControlWithoutHeader : TabControl +{ + public TabControlWithoutHeader() + { + if (!DesignMode) Multiline = true; + } + + protected override void WndProc(ref Message m) + { + if (m.Msg == 0x1328 && !DesignMode) + m.Result = new IntPtr(1); + else + base.WndProc(ref m); + } +} diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs index d0093c9..854ecae 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs @@ -188,7 +188,7 @@ namespace NovetusLauncher } if (GlobalVars.UserConfiguration.DiscordPresence) { - DiscordRPC.Shutdown(); + IDiscordRPC.Shutdown(); } if (GlobalVars.UserConfiguration.WebProxyEnabled) { diff --git a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs index 7083114..25804dd 100644 --- a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs +++ b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs @@ -30,11 +30,36 @@ namespace NovetusLauncher InitializeComponent(); } + //modified from https://stackoverflow.com/questions/14687658/random-name-generator-in-c-sharp + public static string GenerateName(int len) + { + CryptoRandom r = new CryptoRandom(); + string[] consonants = { "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "l", "n", "p", "q", "r", "s", "sh", "zh", "t", "v", "w", "x" }; + string[] vowels = { "a", "e", "i", "o", "u", "ae", "y" }; + string Name = ""; + Name += consonants[r.Next(consonants.Length)].ToUpper(); + Name += vowels[r.Next(vowels.Length)]; + int b = 2; //b tells how many times a new letter has been added. It's 2 right now because the first two letters are already in the name. + while (b < len) + { + Name += consonants[r.Next(consonants.Length)]; + b++; + Name += vowels[r.Next(vowels.Length)]; + b++; + } + + return Name; + } + private void NovetusConsole_Load(object sender, EventArgs e) { Util.ConsolePrint("Novetus version " + GlobalVars.ProgramInformation.Version + " loaded.", 4); Util.ConsolePrint("Novetus path: " + GlobalPaths.BasePath, 4); - NovetusFuncs.SetupAdminPassword(); + CryptoRandom random = new CryptoRandom(); + string Name1 = GenerateName(random.Next(4, 12)); + string Name2 = GenerateName(random.Next(4, 12)); + GlobalVars.Important = Name1 + Name2; + GlobalVars.Important2 = SecurityFuncs.Encipher(GlobalVars.Important, random.Next(2, 13)); if (argList.Length > 0) { diff --git a/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.cs b/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.cs index 387d3c4..8ffd2c0 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/ClientinfoCreator.cs @@ -108,26 +108,26 @@ public partial class ClientinfoEditor : Form { IsVersion2 = true; label9.Text = curversion + " (v" + GlobalVars.ProgramInformation.Version + ")"; - ConvertedLine = SecurityFuncs.Base64DecodeNew(file); + ConvertedLine = SecurityFuncs.Decode(file, false); } catch (Exception) { label9.Text = "v1 (v1.1)"; - ConvertedLine = SecurityFuncs.Base64DecodeOld(file); + ConvertedLine = SecurityFuncs.Decode(file, true); } string[] result = ConvertedLine.Split('|'); - usesplayername = SecurityFuncs.Base64Decode(result[0]); - usesid = SecurityFuncs.Base64Decode(result[1]); - warning = SecurityFuncs.Base64Decode(result[2]); - legacymode = SecurityFuncs.Base64Decode(result[3]); - clientmd5 = SecurityFuncs.Base64Decode(result[4]); - scriptmd5 = SecurityFuncs.Base64Decode(result[5]); - desc = SecurityFuncs.Base64Decode(result[6]); - locked = SecurityFuncs.Base64Decode(result[7]); - fix2007 = SecurityFuncs.Base64Decode(result[8]); - alreadyhassecurity = SecurityFuncs.Base64Decode(result[9]); - cmdargsorclientoptions = SecurityFuncs.Base64Decode(result[10]); + usesplayername = SecurityFuncs.Decode(result[0]); + usesid = SecurityFuncs.Decode(result[1]); + warning = SecurityFuncs.Decode(result[2]); + legacymode = SecurityFuncs.Decode(result[3]); + clientmd5 = SecurityFuncs.Decode(result[4]); + scriptmd5 = SecurityFuncs.Decode(result[5]); + desc = SecurityFuncs.Decode(result[6]); + locked = SecurityFuncs.Decode(result[7]); + fix2007 = SecurityFuncs.Decode(result[8]); + alreadyhassecurity = SecurityFuncs.Decode(result[9]); + cmdargsorclientoptions = SecurityFuncs.Decode(result[10]); folders = "False"; usescustomname = "False"; customname = ""; @@ -137,19 +137,19 @@ public partial class ClientinfoEditor : Form { if (IsVersion2) { - commandargsver2 = SecurityFuncs.Base64Decode(result[11]); + commandargsver2 = SecurityFuncs.Decode(result[11]); bool parsedValue; if (bool.TryParse(commandargsver2, out parsedValue)) { - folders = SecurityFuncs.Base64Decode(result[11]); - commandargsver2 = SecurityFuncs.Base64Decode(result[12]); + folders = SecurityFuncs.Decode(result[11]); + commandargsver2 = SecurityFuncs.Decode(result[12]); bool parsedValue2; if (bool.TryParse(commandargsver2, out parsedValue2)) { - usescustomname = SecurityFuncs.Base64Decode(result[12]); - customname = SecurityFuncs.Base64Decode(result[13]); - commandargsver2 = SecurityFuncs.Base64Decode(result[14]); + usescustomname = SecurityFuncs.Decode(result[12]); + customname = SecurityFuncs.Decode(result[13]); + commandargsver2 = SecurityFuncs.Decode(result[14]); } else { @@ -248,23 +248,23 @@ public partial class ClientinfoEditor : Form if (!string.IsNullOrWhiteSpace(SelectedClientInfoPath)) { string[] lines = { - SecurityFuncs.Base64Encode(SelectedClientInfo.UsesPlayerName.ToString()), - SecurityFuncs.Base64Encode(SelectedClientInfo.UsesID.ToString()), - SecurityFuncs.Base64Encode(SelectedClientInfo.Warning.ToString()), - SecurityFuncs.Base64Encode(SelectedClientInfo.LegacyMode.ToString()), - SecurityFuncs.Base64Encode(SelectedClientInfo.ClientMD5.ToString()), - SecurityFuncs.Base64Encode(SelectedClientInfo.ScriptMD5.ToString()), - SecurityFuncs.Base64Encode(SelectedClientInfo.Description.ToString()), - SecurityFuncs.Base64Encode(Locked.ToString()), - SecurityFuncs.Base64Encode(SelectedClientInfo.Fix2007.ToString()), - SecurityFuncs.Base64Encode(SelectedClientInfo.AlreadyHasSecurity.ToString()), - SecurityFuncs.Base64Encode(((int)SelectedClientInfo.ClientLoadOptions).ToString()), - SecurityFuncs.Base64Encode(SelectedClientInfo.SeperateFolders.ToString()), - SecurityFuncs.Base64Encode(SelectedClientInfo.UsesCustomClientEXEName.ToString()), - SecurityFuncs.Base64Encode(SelectedClientInfo.CustomClientEXEName.ToString()), - SecurityFuncs.Base64Encode(SelectedClientInfo.CommandLineArgs.ToString()) + SecurityFuncs.Encode(SelectedClientInfo.UsesPlayerName.ToString()), + SecurityFuncs.Encode(SelectedClientInfo.UsesID.ToString()), + SecurityFuncs.Encode(SelectedClientInfo.Warning.ToString()), + SecurityFuncs.Encode(SelectedClientInfo.LegacyMode.ToString()), + SecurityFuncs.Encode(SelectedClientInfo.ClientMD5.ToString()), + SecurityFuncs.Encode(SelectedClientInfo.ScriptMD5.ToString()), + SecurityFuncs.Encode(SelectedClientInfo.Description.ToString()), + SecurityFuncs.Encode(Locked.ToString()), + SecurityFuncs.Encode(SelectedClientInfo.Fix2007.ToString()), + SecurityFuncs.Encode(SelectedClientInfo.AlreadyHasSecurity.ToString()), + SecurityFuncs.Encode(((int)SelectedClientInfo.ClientLoadOptions).ToString()), + SecurityFuncs.Encode(SelectedClientInfo.SeperateFolders.ToString()), + SecurityFuncs.Encode(SelectedClientInfo.UsesCustomClientEXEName.ToString()), + SecurityFuncs.Encode(SelectedClientInfo.CustomClientEXEName.ToString()), + SecurityFuncs.Encode(SelectedClientInfo.CommandLineArgs.ToString()) }; - File.WriteAllText(SelectedClientInfoPath + "\\clientinfo.nov", SecurityFuncs.Base64Encode(string.Join("|", lines))); + File.WriteAllText(SelectedClientInfoPath + "\\clientinfo.nov", SecurityFuncs.Encode(string.Join("|", lines))); label9.Text = curversion + " (v" + GlobalVars.ProgramInformation.Version + ")"; diff --git a/Novetus/NovetusLauncher/Forms/ServerBrowser.cs b/Novetus/NovetusLauncher/Forms/ServerBrowser.cs index 6e0d7eb..5b5b295 100644 --- a/Novetus/NovetusLauncher/Forms/ServerBrowser.cs +++ b/Novetus/NovetusLauncher/Forms/ServerBrowser.cs @@ -145,11 +145,11 @@ namespace NovetusLauncher try { string[] initialLine = line.Split('|'); - DecodedLine = SecurityFuncs.Base64DecodeOld(initialLine[1]); + DecodedLine = SecurityFuncs.Decode(initialLine[1], true); } catch (Exception) { - DecodedLine = SecurityFuncs.Base64DecodeOld(line); + DecodedLine = SecurityFuncs.Decode(line, true); } string[] serverInfo = DecodedLine.Split('|'); @@ -253,11 +253,11 @@ namespace NovetusLauncher { public ServerBrowserDef(string name, string ip, string port, string client, string version) { - ServerName = SecurityFuncs.Base64DecodeOld(name); - ServerIP = SecurityFuncs.Base64DecodeOld(ip); - ServerPort = Convert.ToInt32(SecurityFuncs.Base64DecodeOld(port)); - ServerClient = SecurityFuncs.Base64DecodeOld(client); - ServerVersion = SecurityFuncs.Base64DecodeOld(version); + ServerName = SecurityFuncs.Decode(name, true); + ServerIP = SecurityFuncs.Decode(ip, true); + ServerPort = Convert.ToInt32(SecurityFuncs.Decode(port, true)); + ServerClient = SecurityFuncs.Decode(client, true); + ServerVersion = SecurityFuncs.Decode(version, true); } public bool IsValid() diff --git a/Novetus/NovetusLauncher/Novetus.Launcher.csproj b/Novetus/NovetusLauncher/Novetus.Launcher.csproj index 563522b..ae4befa 100644 --- a/Novetus/NovetusLauncher/Novetus.Launcher.csproj +++ b/Novetus/NovetusLauncher/Novetus.Launcher.csproj @@ -21,6 +21,9 @@ False False OnBuildSuccess + false + + publish\ true Disk @@ -33,11 +36,8 @@ true 0 1.0.0.%2a - false false true - - x86 @@ -96,6 +96,11 @@ ..\packages\DotNetZip.1.16.0\lib\net40\DotNetZip.dll + + ..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll + True + True + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll @@ -109,10 +114,21 @@ + + ..\packages\System.AppContext.4.3.0\lib\net463\System.AppContext.dll + True + True + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + ..\packages\System.Console.4.3.0\lib\net46\System.Console.dll + True + True + 3.5 @@ -120,29 +136,136 @@ 3.5 + + ..\packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll + + + ..\packages\System.Diagnostics.Tracing.4.3.0\lib\net462\System.Diagnostics.Tracing.dll + True + True + - + + ..\packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll + True + True + + + ..\packages\System.IO.4.3.0\lib\net462\System.IO.dll + True + True + + + ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll + True + True + + + + ..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll + True + True + + + ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll + True + True + + + ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll + True + True + + + ..\packages\System.Linq.4.3.0\lib\net463\System.Linq.dll + True + True + + + ..\packages\System.Linq.Expressions.4.3.0\lib\net463\System.Linq.Expressions.dll + True + True + ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll - + + ..\packages\System.Net.Http.4.3.0\lib\net46\System.Net.Http.dll + True + True + + + ..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll + True + True + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + ..\packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll + True + True + + + ..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll + True + True + ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + ..\packages\System.Runtime.Extensions.4.3.0\lib\net462\System.Runtime.Extensions.dll + True + True + + + ..\packages\System.Runtime.InteropServices.4.3.0\lib\net463\System.Runtime.InteropServices.dll + True + True + + + ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + True + ..\packages\System.Security.AccessControl.6.0.0\lib\net461\System.Security.AccessControl.dll + + ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll + True + True + + + ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + True + True + + + ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + True + True + + + ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + True + True + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll + + ..\packages\System.Text.RegularExpressions.4.3.0\lib\net463\System.Text.RegularExpressions.dll + True + True + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll @@ -154,6 +277,11 @@ 3.5 + + ..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll + True + True + ..\packages\Titanium.Web.Proxy.3.2.0\lib\net461\Titanium.Web.Proxy.dll @@ -186,6 +314,9 @@ + + Component + Form diff --git a/Novetus/NovetusLauncher/NovetusLauncherEntryPoint.cs b/Novetus/NovetusLauncher/NovetusLauncherEntryPoint.cs index c2f0efb..c374807 100644 --- a/Novetus/NovetusLauncher/NovetusLauncherEntryPoint.cs +++ b/Novetus/NovetusLauncher/NovetusLauncherEntryPoint.cs @@ -97,8 +97,8 @@ namespace NovetusLauncher FileManagement.CreateInitialFileListIfNeededMulti(); FileManagement.CreateAssetCacheDirectories(); - Util.InitUPnP(); - Util.StartDiscord(); + NetFuncs.InitUPnP(); + DiscordRPC.StartDiscord(); } static void Run(string[] args, bool sdk = false, CMDState state = CMDState.CMDOpen) diff --git a/Novetus/NovetusLauncher/packages.config b/Novetus/NovetusLauncher/packages.config index a316aab..deefc0c 100644 --- a/Novetus/NovetusLauncher/packages.config +++ b/Novetus/NovetusLauncher/packages.config @@ -2,16 +2,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Novetus/NovetusURI/Classes/LocalFuncs.cs b/Novetus/NovetusURI/Classes/LocalFuncs.cs index eb5c888..d50b1cb 100644 --- a/Novetus/NovetusURI/Classes/LocalFuncs.cs +++ b/Novetus/NovetusURI/Classes/LocalFuncs.cs @@ -82,11 +82,11 @@ namespace NovetusURI try { string ExtractedArg = LocalVars.SharedArgs.Replace("novetus://", "").Replace("novetus", "").Replace(":", "").Replace("/", "").Replace("?", ""); - string ConvertedArg = SecurityFuncs.Base64DecodeOld(ExtractedArg); + string ConvertedArg = SecurityFuncs.Decode(ExtractedArg, true); string[] SplitArg = ConvertedArg.Split('|'); - string ip = SecurityFuncs.Base64Decode(SplitArg[0]); - string port = SecurityFuncs.Base64Decode(SplitArg[1]); - string client = SecurityFuncs.Base64Decode(SplitArg[2]); + string ip = SecurityFuncs.Decode(SplitArg[0]); + string port = SecurityFuncs.Decode(SplitArg[1]); + string client = SecurityFuncs.Decode(SplitArg[2]); GlobalVars.UserConfiguration.SelectedClient = client; GlobalVars.CurrentServer.ServerIP = ip; GlobalVars.CurrentServer.ServerPort = Convert.ToInt32(port); diff --git a/Novetus/NovetusURI/Forms/LoaderForm.cs b/Novetus/NovetusURI/Forms/LoaderForm.cs index eb21161..eaf536d 100644 --- a/Novetus/NovetusURI/Forms/LoaderForm.cs +++ b/Novetus/NovetusURI/Forms/LoaderForm.cs @@ -13,53 +13,6 @@ namespace NovetusURI #region URI Loader public partial class LoaderForm : Form { - #region Private Variables - private DiscordRPC.EventHandlers handlers; - #endregion - - #region Discord - public void ReadyCallback() - { - } - - public void DisconnectedCallback(int errorCode, string message) - { - } - - public void ErrorCallback(int errorCode, string message) - { - } - - public void JoinCallback(string secret) - { - } - - public void SpectateCallback(string secret) - { - } - - public void RequestCallback(DiscordRPC.JoinRequest request) - { - } - - void StartDiscord() - { - if (GlobalVars.UserConfiguration.DiscordPresence) - { - handlers = new DiscordRPC.EventHandlers(); - handlers.readyCallback = ReadyCallback; - handlers.disconnectedCallback += DisconnectedCallback; - handlers.errorCallback += ErrorCallback; - handlers.joinCallback += JoinCallback; - handlers.spectateCallback += SpectateCallback; - handlers.requestCallback += RequestCallback; - DiscordRPC.Initialize(GlobalVars.appid, ref handlers, true, ""); - - ClientManagement.UpdateRichPresence(GlobalVars.LauncherState.LoadingURI, true); - } - } - #endregion - #region Constructor public LoaderForm() { @@ -131,7 +84,7 @@ namespace NovetusURI if (GlobalVars.UserConfiguration.DiscordPresence) { ClientManagement.UpdateStatus(label1, "Starting Discord Rich Presence..."); - StartDiscord(); + DiscordRPC.StartDiscord(); } ClientManagement.UpdateStatus(label1, "Launching Game..."); LocalFuncs.SetupURIValues(); diff --git a/Novetus/NovetusURI/Novetus.URI.csproj b/Novetus/NovetusURI/Novetus.URI.csproj index a2e1e3c..92c8972 100644 --- a/Novetus/NovetusURI/Novetus.URI.csproj +++ b/Novetus/NovetusURI/Novetus.URI.csproj @@ -53,6 +53,11 @@ C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\BrotliSharpLib.0.3.3\lib\net451\BrotliSharpLib.dll + + ..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll + True + True + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll @@ -63,32 +68,151 @@ ..\packages\NLog.5.1.0\lib\net46\NLog.dll + + ..\packages\System.AppContext.4.3.0\lib\net463\System.AppContext.dll + True + True + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + ..\packages\System.Console.4.3.0\lib\net46\System.Console.dll + True + True + - + + ..\packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll + + + ..\packages\System.Diagnostics.Tracing.4.3.0\lib\net462\System.Diagnostics.Tracing.dll + True + True + + + ..\packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll + True + True + + + ..\packages\System.IO.4.3.0\lib\net462\System.IO.dll + True + True + + + ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll + True + True + + + + ..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll + True + True + + + ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll + True + True + + + ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll + True + True + + + ..\packages\System.Linq.4.3.0\lib\net463\System.Linq.dll + True + True + + + ..\packages\System.Linq.Expressions.4.3.0\lib\net463\System.Linq.Expressions.dll + True + True + ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + ..\packages\System.Net.Http.4.3.0\lib\net46\System.Net.Http.dll + True + True + + + ..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll + True + True + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + ..\packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll + True + True + + + ..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll + True + True + ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + ..\packages\System.Runtime.Extensions.4.3.0\lib\net462\System.Runtime.Extensions.dll + True + True + + + ..\packages\System.Runtime.InteropServices.4.3.0\lib\net463\System.Runtime.InteropServices.dll + True + True + + + ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + True + ..\packages\System.Security.AccessControl.6.0.0\lib\net461\System.Security.AccessControl.dll + + ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll + True + True + + + ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + True + True + + + ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + True + True + + + ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + True + True + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll + + ..\packages\System.Text.RegularExpressions.4.3.0\lib\net463\System.Text.RegularExpressions.dll + True + True + C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll @@ -102,6 +226,11 @@ + + ..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll + True + True + ..\packages\Titanium.Web.Proxy.3.2.0\lib\net461\Titanium.Web.Proxy.dll @@ -126,6 +255,10 @@ Forms\CharCustom\Extended\CharacterCustomizationExtended.designer.cs CharacterCustomizationExtended.cs + + Classes\TabControlWithoutHeader.cs + Component + diff --git a/Novetus/NovetusURI/packages.config b/Novetus/NovetusURI/packages.config index 530607d..b532d6a 100644 --- a/Novetus/NovetusURI/packages.config +++ b/Novetus/NovetusURI/packages.config @@ -1,16 +1,62 @@  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md index f74c0af..932ad15 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,16 +4,11 @@ |Stable Versions|Supported| |-------|-------| -|1.2.4.1|:white_check_mark:| -|1.2.4.1 (lite) |:white_check_mark:| +| 1.3 |:white_check_mark:| |Snapshots|Supported| |-------|-------| -| 1.2.5 |:white_check_mark:| - -|In Development|Supported| -|-------|-------| -| 1.3 (1.2.5 Refresh)|:white_check_mark:| +| 1.3 |:white_check_mark:| ## Reporting a Vulnerability diff --git a/changelog.txt b/changelog.txt index 41a98c4..c66acf8 100644 --- a/changelog.txt +++ b/changelog.txt @@ -4,6 +4,7 @@ Enhancements: - Merged some static APIs into one extension. - Restored the Help button functionality. - All clients now work properly with the Web Proxy. +- Rearraged folder layout. ---------------------------------------------------------------------------- 1.3 Snapshot v22.8412.32591.1 Enhancements: -- 2.40.1 From 8fa0547c2e9422dd68b15702af12ae263c8fb641 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Jan 2023 20:41:36 +0000 Subject: [PATCH 30/85] Bump System.Text.RegularExpressions in /Novetus/NovetusLauncher Bumps System.Text.RegularExpressions from 4.3.0 to 4.3.1. --- updated-dependencies: - dependency-name: System.Text.RegularExpressions dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Novetus/NovetusLauncher/packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Novetus/NovetusLauncher/packages.config b/Novetus/NovetusLauncher/packages.config index deefc0c..5296bbe 100644 --- a/Novetus/NovetusLauncher/packages.config +++ b/Novetus/NovetusLauncher/packages.config @@ -52,7 +52,7 @@ - + -- 2.40.1 From 63e3d05404c6b52fcff0af6e0f4991ab47995a53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Jan 2023 20:41:36 +0000 Subject: [PATCH 31/85] Bump System.Text.RegularExpressions in /Novetus/Novetus.Bootstrapper Bumps System.Text.RegularExpressions from 4.3.0 to 4.3.1. --- updated-dependencies: - dependency-name: System.Text.RegularExpressions dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Novetus/Novetus.Bootstrapper/packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Novetus/Novetus.Bootstrapper/packages.config b/Novetus/Novetus.Bootstrapper/packages.config index 5ff341a..c40d433 100644 --- a/Novetus/Novetus.Bootstrapper/packages.config +++ b/Novetus/Novetus.Bootstrapper/packages.config @@ -41,7 +41,7 @@ - + -- 2.40.1 From e24bf4f86c0233a758579ae44636222d4879b8a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Jan 2023 20:41:36 +0000 Subject: [PATCH 32/85] Bump System.Net.Http in /Novetus/Novetus.Bootstrapper Bumps System.Net.Http from 4.3.0 to 4.3.4. --- updated-dependencies: - dependency-name: System.Net.Http dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Novetus/Novetus.Bootstrapper/packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Novetus/Novetus.Bootstrapper/packages.config b/Novetus/Novetus.Bootstrapper/packages.config index 5ff341a..5b12b21 100644 --- a/Novetus/Novetus.Bootstrapper/packages.config +++ b/Novetus/Novetus.Bootstrapper/packages.config @@ -21,7 +21,7 @@ - + -- 2.40.1 From 2a33e120c278543f669f7b45b7ee901a860cabfd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Jan 2023 20:41:37 +0000 Subject: [PATCH 33/85] Bump System.Net.Http from 4.3.0 to 4.3.4 in /Novetus/NovetusLauncher Bumps System.Net.Http from 4.3.0 to 4.3.4. --- updated-dependencies: - dependency-name: System.Net.Http dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Novetus/NovetusLauncher/packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Novetus/NovetusLauncher/packages.config b/Novetus/NovetusLauncher/packages.config index deefc0c..cca7b4b 100644 --- a/Novetus/NovetusLauncher/packages.config +++ b/Novetus/NovetusLauncher/packages.config @@ -28,7 +28,7 @@ - + -- 2.40.1 From 3c9358c1c56e2083bce196618c0083570c01c888 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Jan 2023 20:41:37 +0000 Subject: [PATCH 34/85] Bump System.Net.Http from 4.3.0 to 4.3.4 in /Novetus/NovetusURI Bumps System.Net.Http from 4.3.0 to 4.3.4. --- updated-dependencies: - dependency-name: System.Net.Http dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Novetus/NovetusURI/packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Novetus/NovetusURI/packages.config b/Novetus/NovetusURI/packages.config index b532d6a..38728c7 100644 --- a/Novetus/NovetusURI/packages.config +++ b/Novetus/NovetusURI/packages.config @@ -27,7 +27,7 @@ - + -- 2.40.1 From 6adfefe0356f1e46013b8433cecd5c792e8661d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Jan 2023 20:44:43 +0000 Subject: [PATCH 35/85] Bump System.Text.RegularExpressions in /Novetus/NovetusURI Bumps System.Text.RegularExpressions from 4.3.0 to 4.3.1. --- updated-dependencies: - dependency-name: System.Text.RegularExpressions dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Novetus/NovetusURI/packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Novetus/NovetusURI/packages.config b/Novetus/NovetusURI/packages.config index 38728c7..0811972 100644 --- a/Novetus/NovetusURI/packages.config +++ b/Novetus/NovetusURI/packages.config @@ -51,7 +51,7 @@ - + -- 2.40.1 From 9aaff22db066a6ca3ae0722c2cf8e25ed30e47e2 Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 13 Jan 2023 13:50:51 -0700 Subject: [PATCH 36/85] unload unnecessary package --- Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj | 3 --- Novetus/Novetus.Bootstrapper/packages.config | 1 - Novetus/NovetusLauncher/Novetus.Launcher.csproj | 3 --- Novetus/NovetusLauncher/packages.config | 1 - Novetus/NovetusURI/Novetus.URI.csproj | 3 --- Novetus/NovetusURI/packages.config | 1 - 6 files changed, 12 deletions(-) diff --git a/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj b/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj index 2aa5177..88b9687 100644 --- a/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj +++ b/Novetus/Novetus.Bootstrapper/Novetus.Bootstrapper.csproj @@ -65,9 +65,6 @@ True - - ..\packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll - ..\packages\System.Diagnostics.Tracing.4.3.0\lib\net462\System.Diagnostics.Tracing.dll True diff --git a/Novetus/Novetus.Bootstrapper/packages.config b/Novetus/Novetus.Bootstrapper/packages.config index 2999112..ce8134e 100644 --- a/Novetus/Novetus.Bootstrapper/packages.config +++ b/Novetus/Novetus.Bootstrapper/packages.config @@ -9,7 +9,6 @@ - diff --git a/Novetus/NovetusLauncher/Novetus.Launcher.csproj b/Novetus/NovetusLauncher/Novetus.Launcher.csproj index ae4befa..357bcde 100644 --- a/Novetus/NovetusLauncher/Novetus.Launcher.csproj +++ b/Novetus/NovetusLauncher/Novetus.Launcher.csproj @@ -136,9 +136,6 @@ 3.5 - - ..\packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll - ..\packages\System.Diagnostics.Tracing.4.3.0\lib\net462\System.Diagnostics.Tracing.dll True diff --git a/Novetus/NovetusLauncher/packages.config b/Novetus/NovetusLauncher/packages.config index a59fff2..d359033 100644 --- a/Novetus/NovetusLauncher/packages.config +++ b/Novetus/NovetusLauncher/packages.config @@ -15,7 +15,6 @@ - diff --git a/Novetus/NovetusURI/Novetus.URI.csproj b/Novetus/NovetusURI/Novetus.URI.csproj index 92c8972..0858c9c 100644 --- a/Novetus/NovetusURI/Novetus.URI.csproj +++ b/Novetus/NovetusURI/Novetus.URI.csproj @@ -84,9 +84,6 @@ True - - ..\packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll - ..\packages\System.Diagnostics.Tracing.4.3.0\lib\net462\System.Diagnostics.Tracing.dll True diff --git a/Novetus/NovetusURI/packages.config b/Novetus/NovetusURI/packages.config index 0811972..c97854a 100644 --- a/Novetus/NovetusURI/packages.config +++ b/Novetus/NovetusURI/packages.config @@ -14,7 +14,6 @@ - -- 2.40.1 From 607d0bcbb44951bee5093afd6505820ff02002b9 Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 13 Jan 2023 14:21:14 -0700 Subject: [PATCH 37/85] move files, remove many #if clauses --- Novetus/NovetusCore/Classes/Downloader.cs | 7 -- Novetus/NovetusCore/Classes/INIFile.cs | 5 -- .../StorageAndFunctions/ClientManagement.cs | 65 +------------------ .../StorageAndFunctions/FileManagement.cs | 52 --------------- .../StorageAndFunctions/GlobalPaths.cs | 1 + .../StorageAndFunctions/NovetusFuncs.cs | 5 -- .../NovetusCore/StorageAndFunctions/Util.cs | 4 +- .../NovetusLauncher/Forms/NovetusConsole.cs | 4 +- .../Forms/SDK/ClientScriptDocumentation.cs | 2 +- 9 files changed, 8 insertions(+), 137 deletions(-) diff --git a/Novetus/NovetusCore/Classes/Downloader.cs b/Novetus/NovetusCore/Classes/Downloader.cs index 225e9f0..0553751 100644 --- a/Novetus/NovetusCore/Classes/Downloader.cs +++ b/Novetus/NovetusCore/Classes/Downloader.cs @@ -103,14 +103,9 @@ namespace Novetus.Core { read = DownloadFile(fileURL, name); } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif downloadOutcome = "Error when downloading file: " + ex.Message; } finally @@ -214,9 +209,7 @@ namespace Novetus.Core } catch (Exception e) { -#if URI || LAUNCHER || BASICLAUNCHER Util.LogExceptions(e); -#endif if (e is WebException && bytesProcessed == 0) { WebException ex = (WebException)e; diff --git a/Novetus/NovetusCore/Classes/INIFile.cs b/Novetus/NovetusCore/Classes/INIFile.cs index 3e4236c..80e1ca8 100644 --- a/Novetus/NovetusCore/Classes/INIFile.cs +++ b/Novetus/NovetusCore/Classes/INIFile.cs @@ -86,14 +86,9 @@ namespace Novetus.Core return false; } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif return false; } } diff --git a/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs b/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs index 3965103..829f9c9 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/ClientManagement.cs @@ -47,14 +47,9 @@ namespace Novetus.Core GenerateDefaultClientInfo(Path.GetDirectoryName(clientpath)); ReadClientValues(name, initial); } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif Util.ConsolePrint("ERROR - Failed to generate default clientinfo.nov. Info: " + ex.Message, 2); Util.ConsolePrint("Loading default client '" + GlobalVars.ProgramInformation.DefaultClient + "'", 4); name = GlobalVars.ProgramInformation.DefaultClient; @@ -230,14 +225,9 @@ namespace Novetus.Core LoadClientValues(info, clientpath); return info; } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif return null; } } @@ -634,14 +624,9 @@ namespace Novetus.Core } } } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif return; } } @@ -700,14 +685,9 @@ namespace Novetus.Core ApplyClientSettings(info, ClientName, GraphicsMode, MeshDetail, ShadingQuality, MaterialQuality, AA, AASamples, Bevels, Shadows_2008, Shadows_2007, Style_2007, GFXQualityLevel, WindowResolution, FullscreenResolution, ModernResolution); } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif return; } } @@ -739,14 +719,9 @@ namespace Novetus.Core fixedfile = RobloxXML.RemoveInvalidXmlChars(RobloxXML.ReplaceHexadecimalSymbols(oldfile)); doc = XDocument.Parse(fixedfile); } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif return; } @@ -789,14 +764,9 @@ namespace Novetus.Core RobloxXML.EditRenderSettings(doc, "Resolution", ModernResolution.ToString(), XMLTypes.Token); } } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif return; } finally @@ -809,14 +779,9 @@ namespace Novetus.Core } } } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif return; } } @@ -1266,17 +1231,12 @@ namespace Novetus.Core #if URI ValidateFiles(line, validstart, validend, label); #else - ValidateFiles(line, validstart, validend); + ValidateFiles(line, validstart, validend); #endif } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif continue; } } @@ -1287,17 +1247,12 @@ namespace Novetus.Core #if URI ValidateFiles(line, validv2, "", label); #else - ValidateFiles(line, validv2, ""); + ValidateFiles(line, validv2, ""); #endif } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif continue; } } @@ -1413,11 +1368,7 @@ namespace Novetus.Core GlobalVars.ValidatedExtraFiles = 0; } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) -#else - catch (Exception) -#endif { #if URI UpdateStatus(label, "Error: " + ex.Message); @@ -1431,9 +1382,7 @@ namespace Novetus.Core MessageBox.Show("Failed to launch Novetus. (Error: " + ex.Message + ")", "Novetus - Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } #endif -#if URI || LAUNCHER || BASICLAUNCHER Util.LogExceptions(ex); -#endif #if URI //toss the exception back to the URI @@ -1702,14 +1651,9 @@ namespace Novetus.Core return result; } } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif return ""; } } @@ -1805,14 +1749,9 @@ namespace Novetus.Core return source; } } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif return source; } } diff --git a/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs b/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs index af0bb27..59a4baf 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs @@ -336,14 +336,9 @@ namespace Novetus.Core group.Header = group.Header + " (" + group.Items.Count + ")"; }*/ } -#if URI || LAUNCHER || CMD || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif } } @@ -360,14 +355,9 @@ namespace Novetus.Core return Bmp; } -#if URI || LAUNCHER || CMD || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif return null; } } @@ -600,9 +590,7 @@ namespace Novetus.Core catch (Exception ex) { installOutcome = "Error when installing icon: " + ex.Message; -#if URI || LAUNCHER || BASICLAUNCHER Util.LogExceptions(ex); -#endif } } } @@ -697,14 +685,9 @@ namespace Novetus.Core GlobalVars.UserConfiguration.MapPath = GlobalPaths.MapsDir + @"\\" + GlobalVars.ProgramInformation.DefaultMap; GlobalVars.UserConfiguration.MapPathSnip = GlobalPaths.MapsDirBase + @"\\" + GlobalVars.ProgramInformation.DefaultMap; } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif ReadInfoFile(infopath, other); } } @@ -958,14 +941,9 @@ namespace Novetus.Core Config(cfgpath, true); } } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif Config(cfgpath, true); } } @@ -1128,14 +1106,9 @@ namespace Novetus.Core GlobalVars.UserCustomization.ExtraSelectionIsHat = ValueBool(extraishat, DefaultCustomization.ExtraSelectionIsHat); GlobalVars.UserCustomization.ShowHatsInExtra = ValueBool(showhatsonextra, DefaultCustomization.ShowHatsInExtra); } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif Customization(cfgpath, true); } } @@ -1251,14 +1224,9 @@ namespace Novetus.Core break; } } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif ReShadeValues(cfgpath, true, setglobals); } } @@ -1281,14 +1249,9 @@ namespace Novetus.Core goto Failure; } } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif goto Failure; } @@ -1319,14 +1282,9 @@ namespace Novetus.Core goto Failure; } } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif goto Failure; } @@ -1394,14 +1352,9 @@ namespace Novetus.Core download.InitDownloadNoDialog(path); return GlobalPaths.AssetCacheAssetsGameDir + download.fileName; } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif } } @@ -1444,14 +1397,9 @@ namespace Novetus.Core return RobloxXML.GetURLInNodes(doc, assetCacheDef.Class, assetCacheDef.Id[0], item); } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif } } diff --git a/Novetus/NovetusCore/StorageAndFunctions/GlobalPaths.cs b/Novetus/NovetusCore/StorageAndFunctions/GlobalPaths.cs index c34341d..fc95c47 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/GlobalPaths.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/GlobalPaths.cs @@ -29,6 +29,7 @@ namespace Novetus.Core public static readonly string AddonNovetusExts = AddonDir + @"\\novetusexts"; public static readonly string NovetusExtsWebProxy = AddonNovetusExts + @"\\webproxy"; public static readonly string MapsDirCustom = MapsDir + @"\\Custom"; + public static readonly string MiscDir = BasePath + @"\\misc"; public static readonly string MapsDirBase = "maps"; public static readonly string BaseGameDir = "rbxasset://../../../"; public static readonly string AltBaseGameDir = "rbxasset://"; diff --git a/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs b/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs index baec1b7..21f8e71 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/NovetusFuncs.cs @@ -233,14 +233,9 @@ namespace Novetus.Core { ipAddress = new WebClient().DownloadString("https://ipv4.icanhazip.com/").TrimEnd(); } -#if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { Util.LogExceptions(ex); -#else - catch (Exception) - { -#endif ipAddress = "localhost"; } diff --git a/Novetus/NovetusCore/StorageAndFunctions/Util.cs b/Novetus/NovetusCore/StorageAndFunctions/Util.cs index 08cccfc..4556020 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/Util.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/Util.cs @@ -587,18 +587,18 @@ namespace Novetus.Core } } -#if LAUNCHER || URI || BASICLAUNCHER public static void LogExceptions(Exception ex) { string message = (ex.Message != null ? ex.Message.ToString() : "N/A"); ConsolePrint(ex.Source + " Exception: " + message, 2, true); +#if LAUNCHER || URI || BASICLAUNCHER LogPrint("EXCEPTION|MESSAGE: " + message, 2); LogPrint("EXCEPTION|STACK TRACE: " + (!string.IsNullOrWhiteSpace(ex.StackTrace) ? ex.StackTrace : "N/A"), 2); LogPrint("EXCEPTION|ADDITIONAL INFO: " + (ex != null ? ex.ToString() : "N/A"), 2); - } #endif + } //https://stackoverflow.com/questions/27108264/how-to-properly-make-a-http-web-get-request diff --git a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs index 25804dd..b08938b 100644 --- a/Novetus/NovetusLauncher/Forms/NovetusConsole.cs +++ b/Novetus/NovetusLauncher/Forms/NovetusConsole.cs @@ -494,7 +494,7 @@ namespace NovetusLauncher { ClearConsole(); Util.ConsolePrint("Help:", 3, true, false); - Util.ReadTextFileWithColor(GlobalPaths.BasePath + "\\" + GlobalPaths.ConsoleHelpFileName, false); + Util.ReadTextFileWithColor(GlobalPaths.MiscDir + "\\" + GlobalPaths.ConsoleHelpFileName, false); Util.ConsolePrint(GlobalVars.Important2, 0, true, false); ScrollToTop(); } @@ -503,7 +503,7 @@ namespace NovetusLauncher { ClearConsole(); Util.ConsolePrint("ClientScript Documentation:", 3, true); - Util.ReadTextFileWithColor(GlobalPaths.BasePath + "\\" + GlobalPaths.ClientScriptDocumentationFileName, false); + Util.ReadTextFileWithColor(GlobalPaths.MiscDir + "\\" + GlobalPaths.ClientScriptDocumentationFileName, false); ScrollToTop(); } diff --git a/Novetus/NovetusLauncher/Forms/SDK/ClientScriptDocumentation.cs b/Novetus/NovetusLauncher/Forms/SDK/ClientScriptDocumentation.cs index 76f4103..019ef4b 100644 --- a/Novetus/NovetusLauncher/Forms/SDK/ClientScriptDocumentation.cs +++ b/Novetus/NovetusLauncher/Forms/SDK/ClientScriptDocumentation.cs @@ -18,7 +18,7 @@ public partial class ClientScriptDocumentation : Form #region Form Events void ClientScriptDocumentationLoad(object sender, EventArgs e) { - richTextBox1.Text = File.ReadAllText(GlobalPaths.BasePath + "\\documentation.txt"); + richTextBox1.Text = File.ReadAllText(GlobalPaths.MiscDir + "\\" + GlobalPaths.ClientScriptDocumentationFileName); } #endregion } -- 2.40.1 From 278675d001dfbc755b7cfbd3f8712cf73c3e6ec9 Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 13 Jan 2023 14:34:19 -0700 Subject: [PATCH 38/85] dpi awareness --- Novetus/Novetus.Bootstrapper/app.config | 9 ++++++++- Novetus/NovetusLauncher/app.config | 4 ++++ Novetus/NovetusURI/App.config | 4 ++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Novetus/Novetus.Bootstrapper/app.config b/Novetus/Novetus.Bootstrapper/app.config index 3e0e37c..1de3e0d 100644 --- a/Novetus/Novetus.Bootstrapper/app.config +++ b/Novetus/Novetus.Bootstrapper/app.config @@ -1,3 +1,10 @@ - + + + + + + + + diff --git a/Novetus/NovetusLauncher/app.config b/Novetus/NovetusLauncher/app.config index 519a38a..052836e 100644 --- a/Novetus/NovetusLauncher/app.config +++ b/Novetus/NovetusLauncher/app.config @@ -3,6 +3,10 @@ + + + + diff --git a/Novetus/NovetusURI/App.config b/Novetus/NovetusURI/App.config index a99a8bb..d73074e 100644 --- a/Novetus/NovetusURI/App.config +++ b/Novetus/NovetusURI/App.config @@ -3,6 +3,10 @@ + + + + -- 2.40.1 From 018b41684a85078b1a8ef92319167b5d0a14a127 Mon Sep 17 00:00:00 2001 From: Bitl Date: Fri, 13 Jan 2023 14:40:21 -0700 Subject: [PATCH 39/85] add json --- Novetus/NovetusLauncher/Novetus.Launcher.csproj | 12 ++++++++++++ Novetus/NovetusLauncher/packages.config | 4 ++++ Novetus/NovetusURI/Novetus.URI.csproj | 12 ++++++++++++ Novetus/NovetusURI/packages.config | 4 ++++ 4 files changed, 32 insertions(+) diff --git a/Novetus/NovetusLauncher/Novetus.Launcher.csproj b/Novetus/NovetusLauncher/Novetus.Launcher.csproj index 357bcde..6492281 100644 --- a/Novetus/NovetusLauncher/Novetus.Launcher.csproj +++ b/Novetus/NovetusLauncher/Novetus.Launcher.csproj @@ -95,6 +95,9 @@ ..\packages\DotNetZip.1.16.0\lib\net40\DotNetZip.dll + + ..\packages\Microsoft.Bcl.AsyncInterfaces.7.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + ..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll @@ -258,6 +261,12 @@ C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll + + ..\packages\System.Text.Encodings.Web.7.0.0\lib\net462\System.Text.Encodings.Web.dll + + + ..\packages\System.Text.Json.7.0.1\lib\net462\System.Text.Json.dll + ..\packages\System.Text.RegularExpressions.4.3.0\lib\net463\System.Text.RegularExpressions.dll True @@ -267,6 +276,9 @@ C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll + diff --git a/Novetus/NovetusLauncher/packages.config b/Novetus/NovetusLauncher/packages.config index d359033..4523228 100644 --- a/Novetus/NovetusLauncher/packages.config +++ b/Novetus/NovetusLauncher/packages.config @@ -2,6 +2,7 @@ + @@ -51,11 +52,14 @@ + + + diff --git a/Novetus/NovetusURI/Novetus.URI.csproj b/Novetus/NovetusURI/Novetus.URI.csproj index 0858c9c..43e1045 100644 --- a/Novetus/NovetusURI/Novetus.URI.csproj +++ b/Novetus/NovetusURI/Novetus.URI.csproj @@ -53,6 +53,9 @@ C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\BrotliSharpLib.0.3.3\lib\net451\BrotliSharpLib.dll + + ..\packages\Microsoft.Bcl.AsyncInterfaces.7.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + ..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll True @@ -205,6 +208,12 @@ C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll + + ..\packages\System.Text.Encodings.Web.7.0.0\lib\net462\System.Text.Encodings.Web.dll + + + ..\packages\System.Text.Json.7.0.1\lib\net462\System.Text.Json.dll + ..\packages\System.Text.RegularExpressions.4.3.0\lib\net463\System.Text.RegularExpressions.dll True @@ -214,6 +223,9 @@ C:\Users\Bitl\Documents\GitHub\Novetus\Novetus_src\Novetus\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll + diff --git a/Novetus/NovetusURI/packages.config b/Novetus/NovetusURI/packages.config index c97854a..3c686ae 100644 --- a/Novetus/NovetusURI/packages.config +++ b/Novetus/NovetusURI/packages.config @@ -1,6 +1,7 @@  + @@ -50,11 +51,14 @@ + + + -- 2.40.1 From f7098e04f339fb647b6a83bc68a1ca5c968f112d Mon Sep 17 00:00:00 2001 From: Bitl Date: Sat, 14 Jan 2023 18:44:01 -0700 Subject: [PATCH 40/85] Create N_new_final_wiki.png --- Graphics/N_new_final_wiki.png | Bin 0 -> 23970 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Graphics/N_new_final_wiki.png diff --git a/Graphics/N_new_final_wiki.png b/Graphics/N_new_final_wiki.png new file mode 100644 index 0000000000000000000000000000000000000000..6d32030ea08db1de95c7e0f3d8ae2ef76d940435 GIT binary patch literal 23970 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 literal 0 HcmV?d00001 -- 2.40.1 From 4c4445bf9281babd01945e2125cedf05b52fc73f Mon Sep 17 00:00:00 2001 From: Bitl Date: Sun, 15 Jan 2023 20:57:03 -0700 Subject: [PATCH 41/85] new mod addon format. fix hasbadge not working as intended. --- Novetus/NovetusCore/Classes/INIFile.cs | 27 + Novetus/NovetusCore/Classes/Script.cs | 3 + Novetus/NovetusCore/Classes/WebProxy.cs | 48 +- .../StorageAndFunctions/FileManagement.cs | 6 +- .../Classes/Launcher/ModManager.cs | 22 +- .../Forms/LauncherForm/LauncherFormShared.cs | 8 +- .../Stylish/LauncherFormStylish.cs | 3 +- .../Stylish/LauncherFormStylishInterface.xaml | 4 +- .../Forms/SDK/ModCreator.Designer.cs | 82 +- .../NovetusLauncher/Forms/SDK/ModCreator.cs | 15 +- .../NovetusLauncher/Novetus.Launcher.csproj | 5 +- Novetus/NovetusLauncher/packages.config | 3 +- Novetus/NovetusURI/Novetus.URI.csproj | 5 +- Novetus/NovetusURI/packages.config | 3 +- changelog.txt | 18 +- .../novetusexts/webproxy/AwardBadge.cs | 11 +- .../novetusexts/webproxy/HasBadge.cs | 3 +- scripts/batch/github_sync.bat | 14 +- scripts/launcher/Appreciation.rbxl | 2643 ++++++++--------- scripts/launcher/info.ini | 4 +- scripts/launcher/splashes.txt | 11 +- 21 files changed, 1516 insertions(+), 1422 deletions(-) diff --git a/Novetus/NovetusCore/Classes/INIFile.cs b/Novetus/NovetusCore/Classes/INIFile.cs index 80e1ca8..b0dcd09 100644 --- a/Novetus/NovetusCore/Classes/INIFile.cs +++ b/Novetus/NovetusCore/Classes/INIFile.cs @@ -92,6 +92,33 @@ namespace Novetus.Core return false; } } + + public string IniGetKey(string SearchString) + { + try + { + if (File.Exists(path)) + { + string[] lines = File.ReadAllLines(path); + + foreach (string line in lines) + { + if (line.Contains(SearchString)) + { + string Key = line.Replace(line.After("="), "").Replace("=", ""); + return Key; + } + } + } + + return ""; + } + catch (Exception ex) + { + Util.LogExceptions(ex); + return ""; + } + } } #endregion } diff --git a/Novetus/NovetusCore/Classes/Script.cs b/Novetus/NovetusCore/Classes/Script.cs index f22b543..ee0d47b 100644 --- a/Novetus/NovetusCore/Classes/Script.cs +++ b/Novetus/NovetusCore/Classes/Script.cs @@ -223,6 +223,9 @@ error: foreach (CompilerError error in result.Errors) { + if (error.IsWarning) + continue; + ErrorHandler(error, filePath); } diff --git a/Novetus/NovetusCore/Classes/WebProxy.cs b/Novetus/NovetusCore/Classes/WebProxy.cs index 0e95d08..26cb5e2 100644 --- a/Novetus/NovetusCore/Classes/WebProxy.cs +++ b/Novetus/NovetusCore/Classes/WebProxy.cs @@ -245,33 +245,39 @@ namespace Novetus.Core public void Stop() { - if (!Server.ProxyRunning) + try { - Util.ConsolePrint("The web proxy is already turned off.", 2); - return; - } - - Util.ConsolePrint("Web Proxy stopping on port " + GlobalVars.WebProxyPort, 3); - Server.BeforeRequest -= new AsyncEventHandler(OnRequest); - Server.Stop(); - - foreach (IExtension extension in Manager.GetExtensionList().ToArray()) - { - try + if (!Server.ProxyRunning) { - IWebProxyExtension webProxyExtension = extension as IWebProxyExtension; - if (webProxyExtension != null) + Util.ConsolePrint("The web proxy is already turned off.", 2); + return; + } + + Util.ConsolePrint("Web Proxy stopping on port " + GlobalVars.WebProxyPort, 3); + Server.BeforeRequest -= new AsyncEventHandler(OnRequest); + Server.Stop(); + + foreach (IExtension extension in Manager.GetExtensionList().ToArray()) + { + try + { + IWebProxyExtension webProxyExtension = extension as IWebProxyExtension; + if (webProxyExtension != null) + { + webProxyExtension.OnProxyStopped(); + } + } + catch (Exception) { - webProxyExtension.OnProxyStopped(); } } - catch (Exception) - { - } - } - Manager.UnloadExtensions(); - Manager.GetExtensionList().Clear(); + Manager.UnloadExtensions(); + Manager.GetExtensionList().Clear(); + } + catch + { + } } } } diff --git a/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs b/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs index 59a4baf..234bec6 100644 --- a/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs +++ b/Novetus/NovetusCore/StorageAndFunctions/FileManagement.cs @@ -1508,14 +1508,14 @@ namespace Novetus.Core } //MessageBox.Show(lineCount + "\n" + fileCount); - - if (lineCount != fileCount) + // commenting this because frankly the CreateInitialFileList thread should be called upon inital bootup of novetus. + /*if (lineCount != fileCount) { Util.ConsolePrint("WARNING - Initial File List is not relevant to file path. Regenerating.", 5); Thread t = new Thread(CreateInitialFileList); t.IsBackground = true; t.Start(); - } + }*/ } } diff --git a/Novetus/NovetusLauncher/Classes/Launcher/ModManager.cs b/Novetus/NovetusLauncher/Classes/Launcher/ModManager.cs index 498b709..93699e3 100644 --- a/Novetus/NovetusLauncher/Classes/Launcher/ModManager.cs +++ b/Novetus/NovetusLauncher/Classes/Launcher/ModManager.cs @@ -217,7 +217,7 @@ public class ModManager tokenSource.Cancel(); } - public async Task CreateModPackage(string[] filesToPackage, string modName) + public async Task CreateModPackage(string[] filesToPackage, string modName, string modAuthor, string modDesc) { if (globalMode == ModMode.ModInstallation) return; @@ -226,7 +226,24 @@ public class ModManager { try { - string outputSavePath = Path.GetDirectoryName(saveFileDialog1.FileName) + @"\" + modName; + string outputPath = Path.GetDirectoryName(saveFileDialog1.FileName); + string fullModName = modAuthor + " - " + modName; + string outputSavePath = outputPath + @"\" + fullModName; + + if (!Directory.Exists(outputSavePath)) + { + Directory.CreateDirectory(outputSavePath); + } + + List info = new List(); + info.Add(modDesc); + info.Add("FILE PATHS:"); + foreach (string filepath in filesToPackage) + { + info.Add(filepath.Replace(GlobalPaths.RootPath, "")); + } + + File.WriteAllLines(outputSavePath + @"\" + fullModName + "_info.txt", info.ToArray()); int filecount = 0; @@ -271,6 +288,7 @@ public class ModManager Directory.Delete(outputSavePath, true); + //don't include the info file. installOutcome = filecount + " files have been successfully moved and compressed into " + outputSavePath + ".zip!"; } catch (Exception ex) diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs index 854ecae..987e9fc 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/LauncherFormShared.cs @@ -192,13 +192,7 @@ namespace NovetusLauncher } if (GlobalVars.UserConfiguration.WebProxyEnabled) { - try - { - GlobalVars.Proxy.Stop(); - } - catch - { - } + GlobalVars.Proxy.Stop(); } if (!GlobalVars.AppClosed) diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylish.cs b/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylish.cs index 81849fe..e3bb689 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylish.cs +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylish.cs @@ -63,8 +63,7 @@ namespace NovetusLauncher launcherFormStylishInterface1.readmeBox.Text = File.ReadAllText(GlobalPaths.RootPath + "\\README-AND-CREDITS.TXT"); } - launcherFormStylishInterface1.versionLabel.Content = Application.ProductVersion; - launcherFormStylishInterface1.versionNovetusLabel.Content = launcherFormStylishInterface1.launcherForm.GetProductVersion(); + launcherFormStylishInterface1.versionLabel.Content = launcherFormStylishInterface1.launcherForm.GetProductVersion(); ReadConfigValues(true); diff --git a/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylishInterface.xaml b/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylishInterface.xaml index c8ab22d..531f209 100644 --- a/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylishInterface.xaml +++ b/Novetus/NovetusLauncher/Forms/LauncherForm/Stylish/LauncherFormStylishInterface.xaml @@ -854,11 +854,9 @@