浏览代码

work on designing HttpEndpoint interface

randoman 6 年之前
父节点
当前提交
eb2819ca04
共有 44 个文件被更改,包括 802 次插入636 次删除
  1. 3 2
      CHANGELOG.md
  2. 49 1
      README.md
  3. 21 0
      XUnity.AutoTranslator.sln
  4. 29 0
      src/Translators/XUnity.AutoTranslator.Plugin.DummyTranslator/DummyTranslator.cs
  5. 11 0
      src/Translators/XUnity.AutoTranslator.Plugin.DummyTranslator/XUnity.AutoTranslator.Plugin.DummyTranslator.csproj
  6. 21 0
      src/Translators/XUnity.AutoTranslator.Plugin.GoogleTranslate/XUnity.AutoTranslator.Plugin.GoogleTranslate.csproj
  7. 1 1
      src/XUnity.AutoTranslator.Plugin.BepIn/XUnity.AutoTranslator.Plugin.BepIn.csproj
  8. 10 7
      src/XUnity.AutoTranslator.Plugin.Core/AutoTranslationPlugin.cs
  9. 3 7
      src/XUnity.AutoTranslator.Plugin.Core/AutoTranslationState.cs
  10. 1 9
      src/XUnity.AutoTranslator.Plugin.Core/Configuration/Settings.cs
  11. 1 1
      src/XUnity.AutoTranslator.Plugin.Core/Constants/ClrTypes.cs
  12. 1 1
      src/XUnity.AutoTranslator.Plugin.Core/Constants/KnownEndpointNames.cs
  13. 49 0
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/AssemblyLoader.cs
  14. 29 27
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/BaiduTranslateEndpoint.cs
  15. 98 83
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/BingTranslateEndpoint.cs
  16. 13 23
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/BingTranslateLegitimateEndpoint.cs
  17. 17 9
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/CustomHttpEndpoint.cs
  18. 102 156
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/GoogleTranslateEndpoint.cs
  19. 19 26
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/GoogleTranslateLegitimateEndpoint.cs
  20. 21 43
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/HttpEndpoint.cs
  21. 17 12
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/YandexTranslateEndpoint.cs
  22. 1 1
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/ITranslateEndpoint.cs
  23. 29 0
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/InitializationContext.cs
  24. 9 9
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/KnownEndpoints.cs
  25. 5 5
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/ProcessLineProtocol/LecPowerTranslateEndpoint.cs
  26. 1 5
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/ProcessLineProtocol/ProcessLineProtocolEndpoint.cs
  27. 3 3
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Www/ExciteTranslateEndpoint.cs
  28. 5 5
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Www/WatsonTranslateEndpoint.cs
  29. 1 1
      src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Www/WwwEndpoint.cs
  30. 1 1
      src/XUnity.AutoTranslator.Plugin.Core/Extensions/StringBuilderExtensions.cs
  31. 1 1
      src/XUnity.AutoTranslator.Plugin.Core/Logger.cs
  32. 1 1
      src/XUnity.AutoTranslator.Plugin.Core/Web/ConnectionTrackingWebClient.cs
  33. 2 2
      src/XUnity.AutoTranslator.Plugin.Core/Web/HttpSecurity.cs
  34. 0 177
      src/XUnity.AutoTranslator.Plugin.Core/Web/UnityWebClient.cs
  35. 128 0
      src/XUnity.AutoTranslator.Plugin.Core/Web/XUnityWebClient.cs
  36. 42 0
      src/XUnity.AutoTranslator.Plugin.Core/Web/XUnityWebRequest.cs
  37. 29 0
      src/XUnity.AutoTranslator.Plugin.Core/Web/XUnityWebResponse.cs
  38. 1 1
      src/XUnity.AutoTranslator.Plugin.IPA/XUnity.AutoTranslator.Plugin.IPA.csproj
  39. 8 0
      src/XUnity.AutoTranslator.Plugin.Lec/Program.cs
  40. 1 2
      src/XUnity.AutoTranslator.Plugin.Lec/Properties/launchSettings.json
  41. 1 1
      src/XUnity.AutoTranslator.Plugin.UnityInjector/XUnity.AutoTranslator.Plugin.UnityInjector.csproj
  42. 3 2
      src/XUnity.AutoTranslator.Setup/Program.cs
  43. 10 10
      src/XUnity.AutoTranslator.Setup/Properties/Resources.Designer.cs
  44. 4 1
      src/XUnity.AutoTranslator.Setup/Properties/Resources.resx

+ 3 - 2
CHANGELOG.md

@@ -1,8 +1,9 @@
-### 2.19.0
- * FEATURE - UI to control plugin more conveniently (press ALT + X)
+### 3.0.0
+ * FEATURE - UI to control plugin more conveniently (press ALT + 0 (that's a zero))
  * FEATURE - Dynamic selection of translator during game session
  * FEATURE - Support BingTranslate API
  * FEATURE - Support LEC Offline Power Translator 15
+ * FEATURE - Enable custom implementations of translators that can be loaded dynamically
  * MISC - {GameExeName} variable can now be used in configuration of directories and files
  * MISC - Changed the way the 'Custom' endpoint works. See README for more info
  * MISC - Added new configuration 'GameLogTextPaths' to enable special handling of text components that text is being appended to continuously (requires export knowledge to setup)

+ 49 - 1
README.md

@@ -13,6 +13,7 @@
  * [Regarding Redistribution](#regarding-redistribution)
  * [Texture Translation](#texture-translation)
  * [Integrating with Auto Translator](#integrating-with-auto-translator)
+ * [Implementing a Translator](#implementing-a-translator)
  
 ## Introduction
 This is a plugin that is capable of using various online translators to provide on-the-fly translations for various Unity-based games.
@@ -40,13 +41,18 @@ The supported online translators are:
  * [ExciteTranslate](https://anonym.to/?https://www.excite.co.jp/world/english_japanese/), based on the Excite online translation service. Does not require authentication.
    * No limitations, but unstable. Also very slow.
  * Custom. Alternatively you can also specify any custom HTTP url that can be used as a translation endpoint (GET request). This must use the query parameters "from", "to" and "text" and return only a string with the result (try HTTP without SSL first, as unity-mono often has issues with SSL).
-   * Example Endpoint=http://my-custom-translation-service.net/translate
+   * Example Configuration:
+     * Endpoint=Custom
+     * [Custom]
+     * Url=http://my-custom-translation-service.net/translate
    * Example Request: GET http://my-custom-translation-service.net/translate?from=ja&to=en&text=こんにちは
    * Example Response (only body): Hello
    * If someone is willing to implement it, this could provide support for offline translators such as ATLAS or LEC as well, since it enables the scenario where you simply run a local web server that can serve translation requests.
  
 **Do note that if you use any of the online translators that does not require some form of authentication, that this plugin may break at any time.**
 
+Since 3.0.0, you can also implement your own translators. To do so, follow the instruction [here](#implementing-a-translator).
+
 ### About Authenticated Translators
 If you decide to use an authenticated service *do not ever share your key or secret*. If you do so by accident, you should revoke it immediately. Most, if not all services provides an option for this.
 
@@ -221,6 +227,7 @@ The following aims at reducing the number of requests send to the translation en
 
 ## Key Mapping
 The following key inputs are mapped:
+ * ALT + 0: Enable XUnity AutoTranslator UI. (That's a zero, not an O)
  * ALT + T: Alternate between translated and untranslated versions of all texts provided by this plugin.
  * ALT + D: Dump untranslated texts (if no endpoint is configured)
  * ALT + R: Reload translation files. Useful if you change the text and texture files on the fly. Not guaranteed to work for all textures.
@@ -431,3 +438,44 @@ public class MyPlugin : XPluginBase
 ```
 
 This approach requires version 2.15.0 or later!
+
+## Implementing a Translator
+Since version 3.0.0, you can now also implement your own translators.
+
+Follow these steps:
+ * Start a new project in Visual Studio 2017 or later. (Be a good boy and choose the "Class Library (.NET Standard)" template. After choosing that, edit the generated .csproj file and change the TargetFramework element to 'net35')
+ * Add a reference to the XUnity.AutoTranslator.Plugin.Core.dll file.
+ * Create a new class that either:
+   * Implements the `ITranslateEndpoint` interface
+   * Inherits from the `HttpEndpoint` class
+
+Here's two examples that does either:
+
+```C#
+public class DummyTranslator : ITranslateEndpoint
+{
+   public string Id => "Dummy";
+
+   public string FriendlyName => "Dummy";
+
+   public int MaxConcurrency => 50;
+
+   public void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints )
+   {
+
+   }
+
+   public IEnumerator Translate( string untranslatedText, string from, string to, Action<string> success, Action<string, Exception> failure )
+   {
+      success( "Incorrect translation" );
+
+      return null;
+   }
+}
+```
+
+TODO: Example...
+
+After implementing the class, simply build the project and place the generated DLL file in the "Translators" directory (you may have to create it) of the plugin folder. That's it.
+
+

+ 21 - 0
XUnity.AutoTranslator.sln

@@ -6,6 +6,9 @@ MinimumVisualStudioVersion = 10.0.40219.1
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0F9B38FC-4E57-4B83-AF0B-0993B8470823}"
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XUnity.AutoTranslator.Plugin.Core", "src\XUnity.AutoTranslator.Plugin.Core\XUnity.AutoTranslator.Plugin.Core.csproj", "{718A3B1D-A5E5-4223-AD53-45C60C874150}"
+	ProjectSection(ProjectDependencies) = postProject
+		{961123AE-1F4F-4340-B39D-6C6F41B3C237} = {961123AE-1F4F-4340-B39D-6C6F41B3C237}
+	EndProjectSection
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XUnity.AutoTranslator.Plugin.BepIn", "src\XUnity.AutoTranslator.Plugin.BepIn\XUnity.AutoTranslator.Plugin.BepIn.csproj", "{5442ED94-2800-47A4-BBAC-C00FBA676D02}"
 EndProject
@@ -17,6 +20,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XUnity.AutoTranslator.Setup
 	ProjectSection(ProjectDependencies) = postProject
 		{718A3B1D-A5E5-4223-AD53-45C60C874150} = {718A3B1D-A5E5-4223-AD53-45C60C874150}
 		{0A2A6B66-91D4-4A4E-AC77-80C6DD748FCD} = {0A2A6B66-91D4-4A4E-AC77-80C6DD748FCD}
+		{961123AE-1F4F-4340-B39D-6C6F41B3C237} = {961123AE-1F4F-4340-B39D-6C6F41B3C237}
 	EndProjectSection
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XUnity.AutoTranslator.Plugin.UnityInjector", "src\XUnity.AutoTranslator.Plugin.UnityInjector\XUnity.AutoTranslator.Plugin.UnityInjector.csproj", "{12F1D16B-B8E1-4A9D-B65A-044650F15440}"
@@ -28,6 +32,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XUnity.AutoTranslator.Plugin.Lec", "src\XUnity.AutoTranslator.Plugin.Lec\XUnity.AutoTranslator.Plugin.Lec.csproj", "{961123AE-1F4F-4340-B39D-6C6F41B3C237}"
 EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Translators", "Translators", "{7A01BA34-3B96-4910-AC70-462BA59417CB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XUnity.AutoTranslator.Plugin.DummyTranslator", "src\Translators\XUnity.AutoTranslator.Plugin.DummyTranslator\XUnity.AutoTranslator.Plugin.DummyTranslator.csproj", "{7493BA4A-C688-4103-B161-7E578FBB6C0E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XUnity.AutoTranslator.Plugin.GoogleTranslate", "src\Translators\XUnity.AutoTranslator.Plugin.GoogleTranslate\XUnity.AutoTranslator.Plugin.GoogleTranslate.csproj", "{5D9A4F4D-D2D2-4D2B-A58A-F7529DDAF1D0}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -62,6 +72,14 @@ Global
 		{961123AE-1F4F-4340-B39D-6C6F41B3C237}.Debug|Any CPU.Build.0 = Debug|x86
 		{961123AE-1F4F-4340-B39D-6C6F41B3C237}.Release|Any CPU.ActiveCfg = Release|x86
 		{961123AE-1F4F-4340-B39D-6C6F41B3C237}.Release|Any CPU.Build.0 = Release|x86
+		{7493BA4A-C688-4103-B161-7E578FBB6C0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{7493BA4A-C688-4103-B161-7E578FBB6C0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7493BA4A-C688-4103-B161-7E578FBB6C0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{7493BA4A-C688-4103-B161-7E578FBB6C0E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{5D9A4F4D-D2D2-4D2B-A58A-F7529DDAF1D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{5D9A4F4D-D2D2-4D2B-A58A-F7529DDAF1D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{5D9A4F4D-D2D2-4D2B-A58A-F7529DDAF1D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{5D9A4F4D-D2D2-4D2B-A58A-F7529DDAF1D0}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -74,6 +92,9 @@ Global
 		{86BF1F46-44C1-4301-8314-6EC32F74575F} = {0F9B38FC-4E57-4B83-AF0B-0993B8470823}
 		{12F1D16B-B8E1-4A9D-B65A-044650F15440} = {0F9B38FC-4E57-4B83-AF0B-0993B8470823}
 		{961123AE-1F4F-4340-B39D-6C6F41B3C237} = {0F9B38FC-4E57-4B83-AF0B-0993B8470823}
+		{7A01BA34-3B96-4910-AC70-462BA59417CB} = {0F9B38FC-4E57-4B83-AF0B-0993B8470823}
+		{7493BA4A-C688-4103-B161-7E578FBB6C0E} = {7A01BA34-3B96-4910-AC70-462BA59417CB}
+		{5D9A4F4D-D2D2-4D2B-A58A-F7529DDAF1D0} = {7A01BA34-3B96-4910-AC70-462BA59417CB}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {EE803FED-4447-4D19-B3D6-88C56E8DFCCA}

+ 29 - 0
src/Translators/XUnity.AutoTranslator.Plugin.DummyTranslator/DummyTranslator.cs

@@ -0,0 +1,29 @@
+using System;
+using System.Collections;
+using XUnity.AutoTranslator.Plugin.Core.Configuration;
+using XUnity.AutoTranslator.Plugin.Core.Endpoints;
+using XUnity.AutoTranslator.Plugin.Core.Web;
+
+namespace XUnity.AutoTranslator.Plugin.DummyTranslator
+{
+   public class DummyTranslator : ITranslateEndpoint
+   {
+      public string Id => "Dummy";
+
+      public string FriendlyName => "Dummy";
+
+      public int MaxConcurrency => 50;
+
+      public void Initialize( InitializationContext context )
+      {
+
+      }
+
+      public IEnumerator Translate( string untranslatedText, string from, string to, Action<string> success, Action<string, Exception> failure )
+      {
+         success( "Incorrect translation" );
+
+         return null;
+      }
+   }
+}

+ 11 - 0
src/Translators/XUnity.AutoTranslator.Plugin.DummyTranslator/XUnity.AutoTranslator.Plugin.DummyTranslator.csproj

@@ -0,0 +1,11 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net35</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\XUnity.AutoTranslator.Plugin.Core\XUnity.AutoTranslator.Plugin.Core.csproj" />
+  </ItemGroup>
+
+</Project>

+ 21 - 0
src/Translators/XUnity.AutoTranslator.Plugin.GoogleTranslate/XUnity.AutoTranslator.Plugin.GoogleTranslate.csproj

@@ -0,0 +1,21 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net35</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Compile Include="..\..\XUnity.AutoTranslator.Plugin.Core\Endpoints\Http\GoogleTranslateEndpoint.cs" Link="GoogleTranslateEndpoint.cs" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\XUnity.AutoTranslator.Plugin.Core\XUnity.AutoTranslator.Plugin.Core.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Reference Include="UnityEngine">
+      <HintPath>..\..\..\libs\UnityEngine.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+
+</Project>

+ 1 - 1
src/XUnity.AutoTranslator.Plugin.BepIn/XUnity.AutoTranslator.Plugin.BepIn.csproj

@@ -31,7 +31,7 @@
       <ItemGroup>
          <VersionNumber Include="$([System.Text.RegularExpressions.Regex]::Replace(&quot;%(Targets.Version)&quot;, &quot;^(.+?)(\.0+)$&quot;, &quot;$1&quot;))" />
       </ItemGroup>
-      <Exec Command="if $(ConfigurationName) == Release (&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)ExIni.dll&quot; &quot;$(SolutionDir)dist\BepIn\BepInEx\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)XUnity.AutoTranslator.Plugin.Core.dll&quot; &quot;$(SolutionDir)dist\BepIn\BepInEx\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)$(TargetName)$(TargetExt)&quot; &quot;$(SolutionDir)dist\BepIn\BepInEx\&quot;&#xD;&#xA;   COPY /Y &quot;$(SolutionDir)README.md&quot; &quot;$(SolutionDir)dist\BepIn\BepInEx\README (AutoTranslator).md&quot;&#xD;&#xA;   powershell Compress-Archive -Path '$(SolutionDir)dist\BepIn\BepInEx' -DestinationPath '$(SolutionDir)dist\BepIn\XUnity.AutoTranslator-BepIn-@(VersionNumber).zip' -Force)&#xD;&#xA;)" />
+      <Exec Command="if $(ConfigurationName) == Release (&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)ExIni.dll&quot; &quot;$(SolutionDir)dist\BepIn\BepInEx\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)XUnity.AutoTranslator.Plugin.Core.dll&quot; &quot;$(SolutionDir)dist\BepIn\BepInEx\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)$(TargetName)$(TargetExt)&quot; &quot;$(SolutionDir)dist\BepIn\BepInEx\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(SolutionDir)src\XUnity.AutoTranslator.Plugin.Lec\bin\x86\Release\net35\XUnity.AutoTranslator.Plugin.Lec.exe&quot; &quot;$(SolutionDir)dist\BepIn\BepInEx\&quot;&#xD;&#xA;   COPY /Y &quot;$(SolutionDir)README.md&quot; &quot;$(SolutionDir)dist\BepIn\BepInEx\README (AutoTranslator).md&quot;&#xD;&#xA;   powershell Compress-Archive -Path '$(SolutionDir)dist\BepIn\BepInEx' -DestinationPath '$(SolutionDir)dist\BepIn\XUnity.AutoTranslator-BepIn-@(VersionNumber).zip' -Force)&#xD;&#xA;)" />
    </Target>
 
 </Project>

+ 10 - 7
src/XUnity.AutoTranslator.Plugin.Core/AutoTranslationPlugin.cs

@@ -40,7 +40,7 @@ namespace XUnity.AutoTranslator.Plugin.Core
       /// <summary>
       /// Allow the instance to be accessed statically, as only one will exist.
       /// </summary>
-      public static AutoTranslationPlugin Current;
+      internal static AutoTranslationPlugin Current;
 
 
       private XuaWindow _window;
@@ -102,7 +102,7 @@ namespace XUnity.AutoTranslator.Plugin.Core
       private Component _advEngine;
       private float? _nextAdvUpdate;
 
-      private ServiceEndpointConfiguration _servicePoints;
+      private HttpSecurity _httpSecurity;
       private List<ConfiguredEndpoint> _configuredEndpoints;
       private ConfiguredEndpoint _endpoint;
 
@@ -164,10 +164,12 @@ namespace XUnity.AutoTranslator.Plugin.Core
          HooksSetup.InstallImageHooks();
          HooksSetup.InstallTextGetterCompatHooks();
 
-         _servicePoints = new ServiceEndpointConfiguration();
+         _httpSecurity = new HttpSecurity();
          try
          {
-            _configuredEndpoints = KnownEndpoints.CreateEndpoints( gameObject, _servicePoints )
+            var context = new InitializationContext( Config.Current, _httpSecurity );
+
+            _configuredEndpoints = KnownEndpoints.CreateEndpoints( gameObject, context )
                .OrderBy( x => x.Endpoint.FriendlyName )
                .ToList();
          }
@@ -196,7 +198,7 @@ namespace XUnity.AutoTranslator.Plugin.Core
          }
 
          // TODO: Perhaps some bleeding edge check to see if this is required?
-         var callback = _servicePoints.GetCertificateValidationCheck();
+         var callback = _httpSecurity.GetCertificateValidationCheck();
          if( callback != null )
          {
             ServicePointManager.ServerCertificateValidationCallback += callback;
@@ -2003,7 +2005,7 @@ namespace XUnity.AutoTranslator.Plugin.Core
                {
                   RebootPlugin();
                }
-               else if( isAltPressed && Input.GetKeyDown( KeyCode.X ) )
+               else if( isAltPressed && ( Input.GetKeyDown( KeyCode.Alpha0 ) || Input.GetKeyDown( KeyCode.Keypad0 ) ) )
                {
                   _window.IsShown = !_window.IsShown;
                }
@@ -2263,7 +2265,8 @@ namespace XUnity.AutoTranslator.Plugin.Core
 
          Settings.TranslationCount++; // counts as a translation
          _consecutiveErrors++;
-
+         _batchLogicHasFailed = true;
+         
          foreach( var tracker in batch.Trackers )
          {
             tracker.Job.State = TranslationJobState.Failed;

+ 3 - 7
src/XUnity.AutoTranslator.Plugin.Core/AutoTranslationState.cs

@@ -8,12 +8,8 @@ namespace XUnity.AutoTranslator.Plugin.Core
 {
    public static class AutoTranslationState
    {
-      public static int TranslationCount
-      {
-         get
-         {
-            return Settings.TranslationCount;
-         }
-      }
+      public static int TranslationCount => Settings.TranslationCount;
+
+      public static string UserAgent => Settings.UserAgent;
    }
 }

+ 1 - 9
src/XUnity.AutoTranslator.Plugin.Core/Configuration/Settings.cs

@@ -14,6 +14,7 @@ namespace XUnity.AutoTranslator.Plugin.Core.Configuration
    internal static class Settings
    {
       // cannot be changed
+      public static readonly string PluginFolder = "Translators";
       public static readonly int MaxMaxCharactersPerTranslation = 500;
       public static readonly string DefaultLanguage = "en";
       public static readonly string DefaultFromLanguage = "ja";
@@ -195,14 +196,5 @@ namespace XUnity.AutoTranslator.Plugin.Core.Configuration
       private static void Migrate()
       {
       }
-
-      public static string GetUserAgent( string defaultUserAgent )
-      {
-         if( !string.IsNullOrEmpty( UserAgent ) )
-         {
-            return UserAgent;
-         }
-         return defaultUserAgent;
-      }
    }
 }

+ 1 - 1
src/XUnity.AutoTranslator.Plugin.Core/Constants/ClrTypes.cs

@@ -4,7 +4,7 @@ using System.Reflection;
 
 namespace XUnity.AutoTranslator.Plugin.Core.Constants
 {
-   public static class ClrTypes
+   internal static class ClrTypes
    {
       // TextMeshPro
       public static readonly Type TMP_InputField = FindType( "TMPro.TMP_InputField" );

+ 1 - 1
src/XUnity.AutoTranslator.Plugin.Core/Constants/KnownEndpointNames.cs

@@ -5,7 +5,7 @@ using System.Text;
 
 namespace XUnity.AutoTranslator.Plugin.Core.Constants
 {
-   internal static class KnownEndpointNames
+   public static class KnownEndpointNames
    {
       public const string GoogleTranslate = "GoogleTranslate";
    }

+ 49 - 0
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/AssemblyLoader.cs

@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace XUnity.AutoTranslator.Plugin.Core.Endpoints
+{
+   internal static class AssemblyLoader
+   {
+      internal static List<Type> GetAllTypesOf<TService>( string directory )
+      {
+         if( !Directory.Exists( directory ) ) return new List<Type>();
+
+         var files = Directory.GetFiles( directory, "*.dll" );
+         var allTypes = new HashSet<Type>();
+
+         foreach( var file in files )
+         {
+            try
+            {
+               var assemblyName = AssemblyName.GetAssemblyName( file );
+               var assembly = Assembly.Load( assemblyName );
+               var types = GetAllTypesOf<TService>( assembly );
+
+               foreach( var type in types )
+               {
+                  allTypes.Add( type );
+               }
+            }
+            catch( Exception e )
+            {
+               Logger.Current.Error( e, "An error occurred while loading types in assembly: " + file );
+            }
+         }
+
+         return allTypes.ToList();
+      }
+
+      internal static List<Type> GetAllTypesOf<TService>( Assembly assembly )
+      {
+         return assembly
+            .GetTypes()
+            .Where( x => typeof( TService ).IsAssignableFrom( x ) && !x.IsAbstract && !x.IsInterface )
+            .ToList();
+      }
+   }
+}

+ 29 - 27
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/BaiduTranslateEndpoint.cs

@@ -22,42 +22,39 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
       private string _appId;
       private string _appSecret;
 
-      public BaiduTranslateEndpoint()
-      {
-
-      }
-
       public override string Id => "BaiduTranslate";
 
       public override string FriendlyName => "Baidu Translator";
 
-      public override void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints )
+      public override void Initialize( InitializationContext context )
       {
-         _appId = configuration.Preferences[ "Baidu" ][ "BaiduAppId" ].GetOrDefault( "" );
-         _appSecret = configuration.Preferences[ "Baidu" ][ "BaiduAppSecret" ].GetOrDefault( "" );
+         _appId = context.Config.Preferences[ "Baidu" ][ "BaiduAppId" ].GetOrDefault( "" );
+         _appSecret = context.Config.Preferences[ "Baidu" ][ "BaiduAppSecret" ].GetOrDefault( "" );
          if( string.IsNullOrEmpty( _appId ) ) throw new ArgumentException( "The BaiduTranslate endpoint requires an App Id which has not been provided." );
          if( string.IsNullOrEmpty( _appSecret ) ) throw new ArgumentException( "The BaiduTranslate endpoint requires an App Secret which has not been provided." );
 
-         servicePoints.EnableHttps( "api.fanyi.baidu.com" );
+         context.HttpSecurity.EnableSslFor( "api.fanyi.baidu.com" );
       }
 
-      private static string CreateMD5( string input )
+      public override XUnityWebRequest CreateTranslationRequest( string untranslatedText, string from, string to )
       {
-         byte[] inputBytes = Encoding.UTF8.GetBytes( input );
-         byte[] hashBytes = HashMD5.ComputeHash( inputBytes );
+         string salt = DateTime.UtcNow.Millisecond.ToString();
+         var md5 = CreateMD5( _appId + untranslatedText + salt + _appSecret );
 
-         StringBuilder sb = new StringBuilder();
-         for( int i = 0 ; i < hashBytes.Length ; i++ )
-         {
-            sb.Append( hashBytes[ i ].ToString( "X2" ) );
-         }
-         return sb.ToString().ToLower();
-      }
+         var request = new XUnityWebRequest(
+            string.Format(
+               HttpServicePointTemplateUrl,
+               WWW.EscapeURL( untranslatedText ),
+               from,
+               to,
+               _appId,
+               salt,
+               md5 ) );
 
-      public override void ApplyHeaders( WebHeaderCollection headers )
-      {
-         headers[ HttpRequestHeader.UserAgent ] = Settings.GetUserAgent( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36" );
-         headers[ HttpRequestHeader.AcceptCharset ] = "UTF-8";
+         request.Headers[ HttpRequestHeader.UserAgent ] = string.IsNullOrEmpty( AutoTranslationState.UserAgent ) ? "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36" : AutoTranslationState.UserAgent;
+         request.Headers[ HttpRequestHeader.AcceptCharset ] = "UTF-8";
+
+         return request;
       }
 
       public override bool TryExtractTranslated( string result, out string translated )
@@ -96,12 +93,17 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
          }
       }
 
-      public override string GetServiceUrl( string untranslatedText, string from, string to )
+      private static string CreateMD5( string input )
       {
-         string salt = DateTime.UtcNow.Millisecond.ToString();
-         var md5 = CreateMD5( _appId + untranslatedText + salt + _appSecret );
+         byte[] inputBytes = Encoding.UTF8.GetBytes( input );
+         byte[] hashBytes = HashMD5.ComputeHash( inputBytes );
 
-         return string.Format( HttpServicePointTemplateUrl, WWW.EscapeURL( untranslatedText ), from, to, _appId, salt, md5 );
+         StringBuilder sb = new StringBuilder();
+         for( int i = 0 ; i < hashBytes.Length ; i++ )
+         {
+            sb.Append( hashBytes[ i ].ToString( "X2" ) );
+         }
+         return sb.ToString().ToLower();
       }
    }
 }

+ 98 - 83
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/BingTranslateEndpoint.cs

@@ -56,42 +56,84 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
 
       public override string FriendlyName => "Bing Translator";
 
-      public override void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints )
+      public override void Initialize( InitializationContext context )
       {
          // Configure service points / service point manager
-         servicePoints.EnableHttps( "www.bing.com" );
+         context.HttpSecurity.EnableSslFor( "www.bing.com" );
       }
 
-      public override void ApplyHeaders( WebHeaderCollection headers )
+      public override XUnityWebRequest CreateTranslationRequest( string untranslatedText, string from, string to )
       {
-         headers[ HttpRequestHeader.UserAgent ] = Settings.GetUserAgent( DefaultUserAgent );
+         _translationCount++;
+         string address = null;
+
+         if( _ig == null || _iid == null )
+         {
+            address = HttpsServicePointTemplateUrlWithoutIG;
+         }
+         else
+         {
+            address = string.Format( HttpsServicePointTemplateUrl, _ig, _iid, _translationCount );
+         }
+
+         var data = string.Format( RequestTemplate, WWW.EscapeURL( untranslatedText ), from, to );
+
+         var request = new XUnityWebRequest( "POST", address, data );
+
+         request.Cookies = _cookieContainer;
+         AddHeaders( request, true );
+
+         return request;
+      }
+
+      private XUnityWebRequest CreateWebSiteRequest()
+      {
+         var request = new XUnityWebRequest( HttpsTranslateUserSite );
+
+         request.Cookies = _cookieContainer;
+         AddHeaders( request, false );
+
+         return request;
+      }
+
+      private void AddHeaders( XUnityWebRequest request, bool isTranslationRequest )
+      {
+         request.Headers[ HttpRequestHeader.UserAgent ] = string.IsNullOrEmpty( AutoTranslationState.UserAgent ) ? DefaultUserAgent : AutoTranslationState.UserAgent;
 
          if( AcceptLanguage != null )
          {
-            headers[ HttpRequestHeader.AcceptLanguage ] = AcceptLanguage;
+            request.Headers[ HttpRequestHeader.AcceptLanguage ] = AcceptLanguage;
          }
          if( Accept != null )
          {
-            headers[ HttpRequestHeader.Accept ] = Accept;
+            request.Headers[ HttpRequestHeader.Accept ] = Accept;
          }
-         if( Referer != null )
+         if( Referer != null && isTranslationRequest )
          {
-            headers[ HttpRequestHeader.Referer ] = Referer;
+            request.Headers[ HttpRequestHeader.Referer ] = Referer;
          }
-         if( Origin != null )
+         if( Origin != null && isTranslationRequest )
          {
-            headers[ "Origin" ] = Origin;
+            request.Headers[ "Origin" ] = Origin;
          }
          if( AcceptCharset != null )
          {
-            headers[ HttpRequestHeader.AcceptCharset ] = AcceptCharset;
+            request.Headers[ HttpRequestHeader.AcceptCharset ] = AcceptCharset;
          }
-         if( ContentType != null )
+         if( ContentType != null && isTranslationRequest )
          {
-            headers[ HttpRequestHeader.ContentType ] = ContentType;
+            request.Headers[ HttpRequestHeader.ContentType ] = ContentType;
          }
       }
 
+      public override void InspectTranslationResponse( XUnityWebResponse response )
+      {
+         CookieCollection cookies = response.NewCookies;
+
+         // FIXME: Is this needed? Should already be added
+         _cookieContainer.Add( cookies );
+      }
+
       public override IEnumerator OnBeforeTranslate()
       {
          if( !_hasSetup || AutoTranslationState.TranslationCount % _resetAfter == 0 )
@@ -110,65 +152,66 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
 
       public IEnumerator SetupIGAndIID()
       {
-         string error = null;
-         UnityWebResponse downloadResult = null;
+         XUnityWebResponse response = null;
 
          _cookieContainer = new CookieContainer();
          _translationCount = 0;
 
-         var client = Client;
          try
          {
-            ApplyHeaders( client.Headers );
-            client.Headers.Remove( HttpRequestHeader.Referer );
-            client.Headers.Remove( "Origin" );
-            client.Headers.Remove( HttpRequestHeader.ContentType );
-            downloadResult = client.DownloadStringByUnityInstruction( new Uri( HttpsTranslateUserSite ) );
+            var client = new XUnityWebClient();
+            var request = CreateWebSiteRequest();
+            response = client.Send( request );
          }
          catch( Exception e )
          {
-            error = e.ToString();
+            Logger.Current.Warn( e, "An error occurred while setting up BingTranslate IG. Proceeding without..." );
+            yield break;
          }
 
-         if( downloadResult != null )
+         if( Features.SupportsCustomYieldInstruction )
          {
-            if( Features.SupportsCustomYieldInstruction )
-            {
-               yield return downloadResult;
-            }
-            else
+            yield return response;
+         }
+         else
+         {
+            while( response.keepWaiting )
             {
-               while( !downloadResult.IsCompleted )
-               {
-                  yield return new WaitForSeconds( 0.2f );
-               }
+               yield return new WaitForSeconds( 0.2f );
             }
+         }
+
+         InspectTranslationResponse( response );
 
-            error = downloadResult.Error;
-            if( downloadResult.Succeeded && downloadResult.Result != null )
+         // failure
+         if( response.Error != null )
+         {
+            Logger.Current.Warn( response.Error, "An error occurred while setting up BingTranslate IG. Proceeding without..." );
+            yield break;
+         }
+
+         // failure
+         if( response.Result == null )
+         {
+            Logger.Current.Warn( null, "An error occurred while setting up BingTranslate IG. Proceeding without..." );
+            yield break;
+         }
+
+         try
+         {
+            var html = response.Result;
+
+            _ig = Lookup( "ig\":\"", html );
+            _iid = Lookup( ".init(\"/feedback/submission?\",\"", html );
+
+            if( _ig == null || _iid == null )
             {
-               try
-               {
-                  var html = downloadResult.Result;
-
-                  _ig = Lookup( "ig\":\"", html );
-                  _iid = Lookup( ".init(\"/feedback/submission?\",\"", html );
-
-                  if( _ig == null || _iid == null )
-                  {
-                     Logger.Current.Warn( "An error occurred while setting up BingTranslate IG/IID. Proceeding without..." );
-                  }
-               }
-               catch( Exception e )
-               {
-                  error = e.ToString();
-               }
+               Logger.Current.Warn( "An error occurred while setting up BingTranslate IG/IID. Proceeding without..." );
             }
          }
-
-         if( error != null )
+         catch( Exception e )
          {
-            Logger.Current.Warn( "An error occurred while setting up BingTranslate IG. Proceeding without..." + Environment.NewLine + error );
+            Logger.Current.Warn( e, "An error occurred while setting up BingTranslate IG. Proceeding without..." );
          }
       }
 
@@ -194,6 +237,8 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
       {
          try
          {
+            Logger.Current.Warn( result );
+
             var obj = JSON.Parse( result );
 
             var code = obj[ "statusCode" ].AsInt;
@@ -217,35 +262,5 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
             return false;
          }
       }
-
-      public override string GetRequestObject( string untranslatedText, string from, string to )
-      {
-         return string.Format( RequestTemplate, WWW.EscapeURL( untranslatedText ), from, to );
-
-      }
-
-      public override string GetServiceUrl( string untranslatedText, string from, string to )
-      {
-         _translationCount++;
-
-         if( _ig == null || _iid == null )
-         {
-            return HttpsServicePointTemplateUrlWithoutIG;
-         }
-         else
-         {
-            return string.Format( HttpsServicePointTemplateUrl, _ig, _iid, _translationCount );
-         }
-      }
-
-      public override void StoreCookiesFromResponse( HttpWebResponse response )
-      {
-         _cookieContainer.Add( response.Cookies );
-      }
-
-      public override CookieContainer GetCookiesForNewRequest()
-      {
-         return _cookieContainer;
-      }
    }
 }

+ 13 - 23
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/BingTranslateLegitimateEndpoint.cs

@@ -31,36 +31,37 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
 
       private string _key;
 
-      public BingTranslateLegitimateEndpoint()
-      {
-
-      }
-
       public override string Id => "BingTranslateLegitimate";
 
       public override string FriendlyName => "Bing Translator (Authenticated)";
 
-      public override void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints )
+      public override void Initialize( InitializationContext context )
       {
-         _key = Config.Current.Preferences[ "BingLegitimate" ][ "OcpApimSubscriptionKey" ].GetOrDefault( "" );
+         _key = context.Config.Preferences[ "BingLegitimate" ][ "OcpApimSubscriptionKey" ].GetOrDefault( "" );
          if( string.IsNullOrEmpty( _key ) ) throw new Exception( "The BingTranslateLegitimate endpoint requires an API key which has not been provided." );
 
          // Configure service points / service point manager
-         servicePoints.EnableHttps( "api.cognitive.microsofttranslator.com" );
+         context.HttpSecurity.EnableSslFor( "api.cognitive.microsofttranslator.com" );
       }
 
-      public override void ApplyHeaders( WebHeaderCollection headers )
+      public override XUnityWebRequest CreateTranslationRequest( string untranslatedText, string from, string to )
       {
+         var request = new XUnityWebRequest(
+            "POST",
+            string.Format( HttpsServicePointTemplateUrl, from, to ),
+            string.Format( RequestTemplate, untranslatedText.EscapeJson() ) );
+
          if( Accept != null )
          {
-            headers[ HttpRequestHeader.Accept ] = Accept;
+            request.Headers[ HttpRequestHeader.Accept ] = Accept;
          }
          if( ContentType != null )
          {
-            headers[ HttpRequestHeader.ContentType ] = ContentType;
+            request.Headers[ HttpRequestHeader.ContentType ] = ContentType;
          }
+         request.Headers[ "Ocp-Apim-Subscription-Key" ] = _key;
 
-         headers[ "Ocp-Apim-Subscription-Key" ] = _key;
+         return request;
       }
 
       public override bool TryExtractTranslated( string result, out string translated )
@@ -83,16 +84,5 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
             return false;
          }
       }
-
-      public override string GetRequestObject( string untranslatedText, string from, string to )
-      {
-         return string.Format( RequestTemplate, untranslatedText.EscapeJson() );
-
-      }
-
-      public override string GetServiceUrl( string untranslatedText, string from, string to )
-      {
-         return string.Format( HttpsServicePointTemplateUrl, from, to );
-      }
    }
 }

+ 17 - 9
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/CustomHttpEndpoint.cs

@@ -22,28 +22,36 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
 
       public override string Id => "Custom";
 
-      public override string FriendlyName => "Custom";
+      public override string FriendlyName => _friendlyName;
 
-      public override void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints )
+      public override void Initialize( InitializationContext context )
       {
-         _endpoint = configuration.Preferences[ "Custom" ][ "Url" ].GetOrDefault( "" );
+         _endpoint = context.Config.Preferences[ "Custom" ][ "Url" ].GetOrDefault( "" );
          if( string.IsNullOrEmpty( _endpoint ) ) throw new ArgumentException( "The custom endpoint requires a url which has not been provided." );
 
          var uri = new Uri( _endpoint );
-         servicePoints.EnableHttps( uri.Host );
+         context.HttpSecurity.EnableSslFor( uri.Host );
 
          _friendlyName += " (" + uri.Host + ")";
       }
 
-      public override bool TryExtractTranslated( string result, out string translated )
+      public override XUnityWebRequest CreateTranslationRequest( string untranslatedText, string from, string to )
       {
-         translated = result;
-         return true;
+         var request = new XUnityWebRequest(
+            string.Format(
+               ServicePointTemplateUrl,
+               _endpoint,
+               from,
+               to,
+               WWW.EscapeURL( untranslatedText ) ) );
+
+         return request;
       }
 
-      public override string GetServiceUrl( string untranslatedText, string from, string to )
+      public override bool TryExtractTranslated( string result, out string translated )
       {
-         return string.Format( ServicePointTemplateUrl, _endpoint, from, to, WWW.EscapeURL( untranslatedText ) );
+         translated = result;
+         return true;
       }
    }
 }

+ 102 - 156
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/GoogleTranslateEndpoint.cs

@@ -6,7 +6,6 @@ using System.IO;
 using System.Net;
 using System.Reflection;
 using System.Text;
-using Harmony;
 using SimpleJSON;
 using UnityEngine;
 using XUnity.AutoTranslator.Plugin.Core.Configuration;
@@ -19,11 +18,9 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
 {
    internal class GoogleTranslateEndpoint : HttpEndpoint
    {
-      //protected static readonly ConstructorInfo WwwConstructor = Constants.Types.WWW?.GetConstructor( new[] { typeof( string ), typeof( byte[] ), typeof( Dictionary<string, string> ) } );
       private static readonly string HttpsServicePointTemplateUrl = "https://translate.googleapis.com/translate_a/single?client=t&dt=t&sl={0}&tl={1}&ie=UTF-8&oe=UTF-8&tk={2}&q={3}";
       private static readonly string HttpsTranslateUserSite = "https://translate.google.com";
       private static readonly string DefaultUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36";
-      //private static readonly string UserAgentRepository = "https://techblog.willshouse.com/2012/01/03/most-common-user-agents/";
       private static readonly System.Random RandomNumbers = new System.Random();
 
       private static readonly string[] Accepts = new string[] { null, "*/*", "application/json" };
@@ -38,8 +35,6 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
 
       private CookieContainer _cookieContainer;
       private bool _hasSetup = false;
-      //private bool _hasSetupCustomUserAgent = false;
-      //private string _popularUserAgent;
       private long m = 427761;
       private long s = 1179739010;
 
@@ -52,47 +47,73 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
 
       public override string FriendlyName => "Google! Translate";
 
-      public override void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints )
+      public override void Initialize( InitializationContext context )
       {
-         servicePoints.EnableHttps( "translate.google.com", "translate.googleapis.com" );
+         context.HttpSecurity.EnableSslFor( "translate.google.com", "translate.googleapis.com" );
       }
 
-      public override void ApplyHeaders( WebHeaderCollection headers )
+      public override XUnityWebRequest CreateTranslationRequest( string untranslatedText, string from, string to )
       {
-         headers[ HttpRequestHeader.UserAgent ] = Settings.GetUserAgent( DefaultUserAgent );
+         var request = new XUnityWebRequest(
+            string.Format(
+               HttpsServicePointTemplateUrl,
+               from,
+               to,
+               Tk( untranslatedText ),
+               WWW.EscapeURL( untranslatedText ) ) );
+
+         request.Cookies = _cookieContainer;
+         AddHeaders( request, true );
+
+         return request;
+      }
+
+      private XUnityWebRequest CreateWebSiteRequest()
+      {
+         var request = new XUnityWebRequest( HttpsTranslateUserSite );
+
+         request.Cookies = _cookieContainer;
+         AddHeaders( request, false );
 
+         return request;
+      }
+
+      private void AddHeaders( XUnityWebRequest request, bool isTranslationRequest )
+      {
+         request.Headers[ HttpRequestHeader.UserAgent ] = string.IsNullOrEmpty( AutoTranslationState.UserAgent ) ? DefaultUserAgent : AutoTranslationState.UserAgent;
          if( AcceptLanguage != null )
          {
-            headers[ HttpRequestHeader.AcceptLanguage ] = AcceptLanguage;
+            request.Headers[ HttpRequestHeader.AcceptLanguage ] = AcceptLanguage;
          }
          if( Accept != null )
          {
-            headers[ HttpRequestHeader.Accept ] = Accept;
+            request.Headers[ HttpRequestHeader.Accept ] = Accept;
          }
-         if( Referer != null )
+         if( Referer != null && isTranslationRequest )
          {
-            headers[ HttpRequestHeader.Referer ] = Referer;
+            request.Headers[ HttpRequestHeader.Referer ] = Referer;
          }
          if( AcceptCharset != null )
          {
-            headers[ HttpRequestHeader.AcceptCharset ] = AcceptCharset;
+            request.Headers[ HttpRequestHeader.AcceptCharset ] = AcceptCharset;
          }
       }
 
-      public override IEnumerator OnBeforeTranslate()
+      public override void InspectTranslationResponse( XUnityWebResponse response )
       {
-         //if( !_hasSetupCustomUserAgent )
-         //{
-         //   _hasSetupCustomUserAgent = true;
-
-         //   // setup dynamic user agent
-         //   var enumerator = SetupDynamicUserAgent();
-         //   while( enumerator.MoveNext() )
-         //   {
-         //      yield return enumerator.Current;
-         //   }
-         //}
+         CookieCollection cookies = response.NewCookies;
+         foreach( Cookie cookie in cookies )
+         {
+            // redirect cookie to correct domain
+            cookie.Domain = ".googleapis.com";
+         }
+
+         // FIXME: Is this needed? Should already be added
+         _cookieContainer.Add( cookies );
+      }
 
+      public override IEnumerator OnBeforeTranslate()
+      {
          if( !_hasSetup || AutoTranslationState.TranslationCount % 100 == 0 )
          {
             _hasSetup = true;
@@ -106,139 +127,86 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
          }
       }
 
-      //public IEnumerator SetupDynamicUserAgent()
-      //{
-      //   // have to use WWW for this because unity mono is broken
-
-      //   if( WwwConstructor != null )
-      //   {
-      //      object www;
-      //      try
-      //      {
-      //         var headers = new Dictionary<string, string>();
-      //         www = WwwConstructor.Invoke( new object[] { UserAgentRepository, null, headers } );
-      //      }
-      //      catch( Exception e )
-      //      {
-      //         Logger.Current.Warn( e, "An error occurred while retrieving dynamic user agent." );
-      //         yield break;
-      //      }
-
-      //      yield return www;
-
-      //      try
-      //      {
-      //         var error = (string)AccessTools.Property( Constants.Types.WWW, "error" ).GetValue( www, null );
-      //         if( error == null )
-      //         {
-      //            var text = (string)AccessTools.Property( Constants.Types.WWW, "text" ).GetValue( www, null );
-      //            var userAgents = text.GetBetween( "<textarea rows=\"10\" class=\"get-the-list\" onclick=\"this.select()\" readonly=\"readonly\">", "</textarea>" );
-      //            if( userAgents.Length > 42 )
-      //            {
-      //               var reader = new StringReader( userAgents );
-      //               var popularUserAgent = reader.ReadLine();
-      //               if( popularUserAgent.Length > 30 && popularUserAgent.Length < 300 && popularUserAgent.StartsWith( "Mozilla/" ) )
-      //               {
-      //                  _popularUserAgent = popularUserAgent;
-      //               }
-      //               else
-      //               {
-      //                  Logger.Current.Warn( "An error occurred while retrieving dynamic user agent. Could not find a user agent in returned html." );
-      //               }
-      //            }
-      //            else
-      //            {
-      //               Logger.Current.Warn( "An error occurred while retrieving dynamic user agent. Could not find a user agent in returned html." );
-      //            }
-      //         }
-      //         else
-      //         {
-      //            Logger.Current.Warn( "An error occurred while retrieving dynamic user agent. Request failed: " + Environment.NewLine + error );
-      //         }
-      //      }
-      //      catch( Exception e )
-      //      {
-      //         Logger.Current.Warn( e, "An error occurred while retrieving dynamic user agent." );
-      //      }
-      //   }
-      //}
-
       public IEnumerator SetupTKK()
       {
-         string error = null;
-         UnityWebResponse response = null;
+         XUnityWebResponse response = null;
 
          _cookieContainer = new CookieContainer();
 
          try
          {
-            ApplyHeaders( Client.Headers );
-            Client.Headers.Remove( HttpRequestHeader.Referer );
-            response = Client.DownloadStringByUnityInstruction( new Uri( HttpsTranslateUserSite ) );
+            var client = new XUnityWebClient();
+            var request = CreateWebSiteRequest();
+            response = client.Send( request );
          }
          catch( Exception e )
          {
-            error = e.ToString();
+            Logger.Current.Warn( e, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead." );
+            yield break;
          }
 
-         if( response != null )
+         if( Features.SupportsCustomYieldInstruction )
          {
-            if( Features.SupportsCustomYieldInstruction )
-            {
-               yield return response;
-            }
-            else
+            yield return response;
+         }
+         else
+         {
+            while( response.keepWaiting )
             {
-               while( !response.IsCompleted )
-               {
-                  yield return new WaitForSeconds( 0.2f );
-               }
+               yield return new WaitForSeconds( 0.2f );
             }
+         }
+
+         InspectTranslationResponse( response );
 
-            error = response.Error;
-            if( response.Succeeded && response.Result != null )
+         // failure
+         if( response.Error != null )
+         {
+            Logger.Current.Warn( response.Error, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead." );
+            yield break;
+         }
+
+         // failure
+         if( response.Result == null )
+         {
+            Logger.Current.Warn( null, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead." );
+            yield break;
+         }
+
+         try
+         {
+            var html = response.Result;
+
+            bool found = false;
+            string[] lookups = new[] { "tkk:'", "TKK='" };
+            foreach( var lookup in lookups )
             {
-               try
+               var index = html.IndexOf( lookup );
+               if( index > -1 ) // simple string approach
                {
-                  var html = response.Result;
-
-                  bool found = false;
-                  string[] lookups = new[] { "tkk:'", "TKK='" };
-                  foreach( var lookup in lookups )
-                  {
-                     var index = html.IndexOf( lookup );
-                     if( index > -1 ) // simple string approach
-                     {
-                        var startIndex = index + lookup.Length;
-                        var endIndex = html.IndexOf( "'", startIndex );
-                        var result = html.Substring( startIndex, endIndex - startIndex );
-
-                        var parts = result.Split( '.' );
-                        if( parts.Length == 2 )
-                        {
-                           m = long.Parse( parts[ 0 ] );
-                           s = long.Parse( parts[ 1 ] );
-                           found = true;
-                           break;
-                        }
-                     }
-                  }
+                  var startIndex = index + lookup.Length;
+                  var endIndex = html.IndexOf( "'", startIndex );
+                  var result = html.Substring( startIndex, endIndex - startIndex );
 
-                  if( !found )
+                  var parts = result.Split( '.' );
+                  if( parts.Length == 2 )
                   {
-                     Logger.Current.Warn( "An error occurred while setting up GoogleTranslate TKK. Could not locate TKK value. Using fallback TKK values instead." );
+                     m = long.Parse( parts[ 0 ] );
+                     s = long.Parse( parts[ 1 ] );
+                     found = true;
+                     break;
                   }
                }
-               catch( Exception e )
-               {
-                  error = e.ToString();
-               }
             }
-         }
 
-         if( error != null )
+            if( !found )
+            {
+               Logger.Current.Warn( "An error occurred while setting up GoogleTranslate TKK. Could not locate TKK value. Using fallback TKK values instead." );
+            }
+         }
+         catch( Exception e )
          {
-            Logger.Current.Warn( "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead." + Environment.NewLine + error );
+            Logger.Current.Warn( e, "An error occurred while setting up GoogleTranslate TKK. Using fallback TKK values instead." );
          }
       }
 
@@ -334,27 +302,5 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
             return false;
          }
       }
-
-      public override string GetServiceUrl( string untranslatedText, string from, string to )
-      {
-         return string.Format( HttpsServicePointTemplateUrl, from, to, Tk( untranslatedText ), WWW.EscapeURL( untranslatedText ) );
-      }
-
-      public override void StoreCookiesFromResponse( HttpWebResponse response )
-      {
-         CookieCollection cookies = response.Cookies;
-         foreach( Cookie cookie in cookies )
-         {
-            // redirect cookie to correct domain
-            cookie.Domain = ".googleapis.com";
-         }
-
-         _cookieContainer.Add( cookies );
-      }
-
-      public override CookieContainer GetCookiesForNewRequest()
-      {
-         return _cookieContainer;
-      }
    }
 }

+ 19 - 26
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/GoogleTranslateLegitimateEndpoint.cs

@@ -23,26 +23,36 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
 
       private string _key;
 
-      public GoogleTranslateLegitimateEndpoint()
-      {
-
-      }
-
       public override string Id => "GoogleTranslateLegitimate";
 
       public override string FriendlyName => "Google! Translate (Authenticated)";
 
-      public override void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints )
+      public override void Initialize( InitializationContext context )
       {
-         _key = Config.Current.Preferences[ "GoogleLegitimate" ][ "GoogleAPIKey" ].GetOrDefault( "" );
+         _key = context.Config.Preferences[ "GoogleLegitimate" ][ "GoogleAPIKey" ].GetOrDefault( "" );
          if( string.IsNullOrEmpty( _key ) ) throw new Exception( "The GoogleTranslateLegitimate endpoint requires an API key which has not been provided." );
 
          // Configure service points / service point manager
-         servicePoints.EnableHttps( "translation.googleapis.com" );
+         context.HttpSecurity.EnableSslFor( "translation.googleapis.com" );
       }
 
-      public override void ApplyHeaders( WebHeaderCollection headers )
+      public override XUnityWebRequest CreateTranslationRequest( string untranslatedText, string from, string to )
       {
+         var b = new StringBuilder();
+         b.Append( "{" );
+         b.Append( "\"q\":\"" ).Append( untranslatedText.EscapeJson() ).Append( "\"," );
+         b.Append( "\"target\":\"" ).Append( to ).Append( "\"," );
+         b.Append( "\"source\":\"" ).Append( from ).Append( "\"," );
+         b.Append( "\"format\":\"text\"" );
+         b.Append( "}" );
+         var data = b.ToString();
+
+         var request = new XUnityWebRequest(
+            "POST",
+            string.Format( HttpsServicePointTemplateUrl, WWW.EscapeURL( _key ) ),
+            data );
+
+         return request;
       }
 
       public override bool TryExtractTranslated( string result, out string translated )
@@ -73,22 +83,5 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
             return false;
          }
       }
-
-      public override string GetServiceUrl( string untranslatedText, string from, string to )
-      {
-         return string.Format( HttpsServicePointTemplateUrl, WWW.EscapeURL( _key ) );
-      }
-
-      public override string GetRequestObject( string untranslatedText, string from, string to )
-      {
-         var b = new StringBuilder();
-         b.Append( "{" );
-         b.Append( "\"q\":\"" ).Append( untranslatedText.EscapeJson() ).Append( "\"," );
-         b.Append( "\"target\":\"" ).Append( to ).Append( "\"," );
-         b.Append( "\"source\":\"" ).Append( from ).Append( "\"," );
-         b.Append( "\"format\":\"text\"" );
-         b.Append( "}" );
-         return b.ToString();
-      }
    }
 }

+ 21 - 43
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/HttpEndpoint.cs

@@ -11,40 +11,25 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
 {
    public abstract class HttpEndpoint : ITranslateEndpoint
    {
-      public HttpEndpoint()
-      {
-         Client = new UnityWebClient( this );
-      }
-
       public abstract string Id { get; }
 
       public abstract string FriendlyName { get; }
 
-      public UnityWebClient Client { get; }
+      public XUnityWebClient Client { get; }
 
-      public abstract void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints );
+      public int MaxConcurrency => 1;
 
-      public abstract string GetServiceUrl( string untranslatedText, string from, string to );
+      public abstract void Initialize( InitializationContext context );
 
       public abstract bool TryExtractTranslated( string result, out string translated );
 
-      public int MaxConcurrency => 1;
-
-      public virtual string GetRequestObject( string untranslatedText, string from, string to ) => null;
+      public abstract XUnityWebRequest CreateTranslationRequest( string untranslatedText, string from, string to );
 
-      public virtual CookieContainer GetCookiesForNewRequest() => null;
-
-      public virtual IEnumerator OnBeforeTranslate() => null;
-
-      public virtual void StoreCookiesFromResponse( HttpWebResponse response )
+      public virtual void InspectTranslationResponse( XUnityWebResponse response )
       {
-
       }
 
-      public virtual void ApplyHeaders( WebHeaderCollection headers )
-      {
-
-      }
+      public virtual IEnumerator OnBeforeTranslate() => null;
 
       public IEnumerator Translate( string untranslatedText, string from, string to, Action<string> success, Action<string, Exception> failure )
       {
@@ -58,23 +43,13 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
             }
          }
 
-         UnityWebResponse response = null;
+         XUnityWebResponse response = null;
          try
          {
             // prepare request
-            var url = GetServiceUrl( untranslatedText, from, to );
-            var request = GetRequestObject( untranslatedText, from, to );
-            ApplyHeaders( Client.Headers );
-
-            // execute request
-            if( request != null )
-            {
-               response = Client.UploadStringByUnityInstruction( new Uri( url ), request );
-            }
-            else
-            {
-               response = Client.DownloadStringByUnityInstruction( new Uri( url ) );
-            }
+            var client = new XUnityWebClient();
+            var request = CreateTranslationRequest( untranslatedText, from, to );
+            response = client.Send( request );
          }
          catch( Exception e )
          {
@@ -82,12 +57,6 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
             yield break;
          }
 
-         if( response == null )
-         {
-            failure( "Unexpected error occurred while retrieving translation.", null );
-            yield break;
-         }
-
          // wait for completion
          if( Features.SupportsCustomYieldInstruction )
          {
@@ -101,10 +70,19 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
             }
          }
 
+         InspectTranslationResponse( response );
+
+         // failure
+         if( response.Error != null )
+         {
+            failure( "Error occurred while retrieving translation.", response.Error );
+            yield break;
+         }
+
          // failure
-         if( !response.Succeeded || response.Result == null )
+         if( response.Result == null )
          {
-            failure( "Error occurred while retrieving translation." + Environment.NewLine + response.Error, null );
+            failure( "Error occurred while retrieving translation. Nothing was returned.", null );
             yield break;
          }
 

+ 17 - 12
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Http/YandexTranslateEndpoint.cs

@@ -27,19 +27,29 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
       {
       }
 
-      public override void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints )
+      public override void Initialize( InitializationContext context )
       {
-         _key = Config.Current.Preferences[ "Yandex" ][ "YandexAPIKey" ].GetOrDefault( "" );
+         _key = context.Config.Preferences[ "Yandex" ][ "YandexAPIKey" ].GetOrDefault( "" );
          if( string.IsNullOrEmpty( _key ) ) throw new Exception( "The YandexTranslate endpoint requires an API key which has not been provided." );
 
-         servicePoints.EnableHttps( "translate.yandex.net" );
+         context.HttpSecurity.EnableSslFor( "translate.yandex.net" );
       }
 
-      public override void ApplyHeaders( WebHeaderCollection headers )
+      public override XUnityWebRequest CreateTranslationRequest( string untranslatedText, string from, string to )
       {
-         headers[ HttpRequestHeader.UserAgent ] = Settings.GetUserAgent( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.183 Safari/537.36 Vivaldi/1.96.1147.55" );
-         headers[ HttpRequestHeader.Accept ] = "*/*";
-         headers[ HttpRequestHeader.AcceptCharset ] = "UTF-8";
+         var request = new XUnityWebRequest(
+            string.Format(
+               HttpsServicePointTemplateUrl,
+               from,
+               to,
+               WWW.EscapeURL( untranslatedText ),
+               _key ) );
+
+         request.Headers[ HttpRequestHeader.UserAgent ] = string.IsNullOrEmpty( AutoTranslationState.UserAgent ) ? "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.183 Safari/537.36 Vivaldi/1.96.1147.55" : AutoTranslationState.UserAgent;
+         request.Headers[ HttpRequestHeader.Accept ] = "*/*";
+         request.Headers[ HttpRequestHeader.AcceptCharset ] = "UTF-8";
+
+         return request;
       }
 
       public override bool TryExtractTranslated( string result, out string translated )
@@ -81,10 +91,5 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Http
             return false;
          }
       }
-
-      public override string GetServiceUrl( string untranslatedText, string from, string to )
-      {
-         return string.Format( HttpsServicePointTemplateUrl, from, to, WWW.EscapeURL( untranslatedText ), _key );
-      }
    }
 }

+ 1 - 1
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/ITranslateEndpoint.cs

@@ -28,7 +28,7 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints
       /// <summary>
       /// Called during initialization. Use this to initialize plugin or throw exception if impossible.
       /// </summary>
-      void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints );
+      void Initialize( InitializationContext context );
 
       /// <summary>
       /// Attempt to translated the provided untranslated text. Will be used in a "coroutine", so it can be implemented

+ 29 - 0
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/InitializationContext.cs

@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using XUnity.AutoTranslator.Plugin.Core.Configuration;
+using XUnity.AutoTranslator.Plugin.Core.Web;
+
+namespace XUnity.AutoTranslator.Plugin.Core.Endpoints
+{
+   public class InitializationContext
+   {
+      public InitializationContext( IConfiguration config, HttpSecurity httpSecurity )
+      {
+         Config = config;
+         HttpSecurity = httpSecurity;
+      }
+
+      /// <summary>
+      /// Gets the configuration of the plugin, including the directory where
+      /// the configuration file is placed.
+      /// </summary>
+      public IConfiguration Config { get; }
+
+      /// <summary>
+      /// Gets the HttpSecurity class which enables setting up SSL for endpoints.
+      /// </summary>
+      public HttpSecurity HttpSecurity { get; }
+   }
+}

+ 9 - 9
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/KnownEndpoints.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Text;
 using UnityEngine;
@@ -11,25 +12,24 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints
 {
    internal static class KnownEndpoints
    {
-      public static List<ConfiguredEndpoint> CreateEndpoints( GameObject go, ServiceEndpointConfiguration servicePoints )
+      public static List<ConfiguredEndpoint> CreateEndpoints( GameObject go, InitializationContext context )
       {
          var endpoints = new List<ConfiguredEndpoint>();
 
          // could dynamically load types from other assemblies...
-         var types = typeof( KnownEndpoints ).Assembly
-            .GetTypes()
-            .Where( x => typeof( ITranslateEndpoint ).IsAssignableFrom( x ) && !x.IsAbstract && !x.IsInterface )
-            .ToList();
+         var integratedTypes = AssemblyLoader.GetAllTypesOf<ITranslateEndpoint>( typeof( KnownEndpoints ).Assembly );
+         var pluginFolder = Path.Combine( Config.Current.DataPath, Settings.PluginFolder );
+         var dynamicTypes = AssemblyLoader.GetAllTypesOf<ITranslateEndpoint>( pluginFolder );
 
-         foreach( var type in types )
+         foreach( var type in integratedTypes.Union( dynamicTypes ).Distinct() )
          {
-            AddEndpoint( go, servicePoints, endpoints, type );
+            AddEndpoint( go, context, endpoints, type );
          }
 
          return endpoints;
       }
 
-      private static void AddEndpoint( GameObject go, ServiceEndpointConfiguration servicePoints, List<ConfiguredEndpoint> endpoints, Type type )
+      private static void AddEndpoint( GameObject go, InitializationContext context, List<ConfiguredEndpoint> endpoints, Type type )
       {
          ITranslateEndpoint endpoint;
          try
@@ -53,7 +53,7 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints
 
          try
          {
-            endpoint.Initialize( Config.Current, servicePoints );
+            endpoint.Initialize( context );
             endpoints.Add( new ConfiguredEndpoint( endpoint, null ) );
          }
          catch( Exception e )

+ 5 - 5
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/ProcessLineProtocol/LecPowerTranslateEndpoint.cs

@@ -13,16 +13,16 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.ProcessLineProtocol
 
       public override string FriendlyName => "LEC Power Translator 15";
 
-      public override void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints )
+      public override void Initialize( InitializationContext context )
       {
-         var to = configuration.Preferences[ "General" ][ "Language" ].Value;
-         var from = configuration.Preferences[ "General" ][ "FromLanguage" ].Value;
-         var pathToLec = configuration.Preferences[ "LecPowerTranslator15" ][ "Path" ].GetOrDefault( "" );
+         var to = context.Config.Preferences[ "General" ][ "Language" ].Value;
+         var from = context.Config.Preferences[ "General" ][ "FromLanguage" ].Value;
+         var pathToLec = context.Config.Preferences[ "LecPowerTranslator15" ][ "Path" ].GetOrDefault( "" );
          if( string.IsNullOrEmpty( pathToLec ) ) throw new Exception( "The LecPowerTranslator15 requires the path to the installation folder." );
          if( !from.Equals( "ja", StringComparison.OrdinalIgnoreCase ) ) throw new Exception( "Only japanese to english is supported." );
          if( !to.Equals( "en", StringComparison.OrdinalIgnoreCase ) ) throw new Exception( "Only japanese to english is supported." );
 
-         var path1 = configuration.DataPath;
+         var path1 = context.Config.DataPath;
          var exePath1 = Path.Combine( path1, "XUnity.AutoTranslator.Plugin.Lec.exe" );
          var file1Exists = File.Exists( exePath1 );
          var path2 = new FileInfo( typeof( LecPowerTranslateEndpoint ).Assembly.Location ).Directory.FullName;

+ 1 - 5
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/ProcessLineProtocol/ProcessLineProtocolEndpoint.cs

@@ -24,7 +24,7 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.ProcessLineProtocol
 
       public abstract string FriendlyName { get; }
 
-      public abstract void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints );
+      public abstract void Initialize( InitializationContext context );
 
       public int MaxConcurrency => 1;
 
@@ -114,10 +114,6 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.ProcessLineProtocol
          }
       }
 
-      public void OnUpdate()
-      {
-      }
-
       public class StreamReaderResult : CustomYieldInstructionShim
       {
          public void SetCompleted( string result, string error )

+ 3 - 3
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Www/ExciteTranslateEndpoint.cs

@@ -24,14 +24,14 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Www
 
       public override string FriendlyName => "Excite Translator";
 
-      public override void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints )
+      public override void Initialize( InitializationContext context )
       {
-         servicePoints.EnableHttps( "www.excite.co.jp", "excite.co.jp" );
+         context.HttpSecurity.EnableSslFor( "www.excite.co.jp", "excite.co.jp" );
       }
 
       public override void ApplyHeaders( Dictionary<string, string> headers )
       {
-         headers[ "User-Agent" ] = Settings.GetUserAgent( "Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53" );
+         headers[ "User-Agent" ] = string.IsNullOrEmpty( AutoTranslationState.UserAgent ) ? "Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53" : AutoTranslationState.UserAgent;
          headers[ "Accept" ] = "text/html";
          //headers[ "Accept-Charset" ] = "UTF-8";
          //headers[ "DNT" ] = "1";

+ 5 - 5
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Www/WatsonTranslateEndpoint.cs

@@ -28,11 +28,11 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Www
 
       public override string FriendlyName => "Watson Language Translator";
 
-      public override void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints )
+      public override void Initialize( InitializationContext context )
       {
-         _url = Config.Current.Preferences[ "Watson" ][ "WatsonAPIUrl" ].GetOrDefault( "" );
-         _username = Config.Current.Preferences[ "Watson" ][ "WatsonAPIUsername" ].GetOrDefault( "" );
-         _password = Config.Current.Preferences[ "Watson" ][ "WatsonAPIPassword" ].GetOrDefault( "" );
+         _url = context.Config.Preferences[ "Watson" ][ "WatsonAPIUrl" ].GetOrDefault( "" );
+         _username = context.Config.Preferences[ "Watson" ][ "WatsonAPIUsername" ].GetOrDefault( "" );
+         _password = context.Config.Preferences[ "Watson" ][ "WatsonAPIPassword" ].GetOrDefault( "" );
          if( string.IsNullOrEmpty( _url ) ) throw new Exception( "The WatsonTranslate endpoint requires a url which has not been provided." );
          if( string.IsNullOrEmpty( _username ) ) throw new Exception( "The WatsonTranslate endpoint requires a username which has not been provided." );
          if( string.IsNullOrEmpty( _password ) ) throw new Exception( "The WatsonTranslate endpoint requires a password which has not been provided." );
@@ -42,7 +42,7 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Www
 
       public override void ApplyHeaders( Dictionary<string, string> headers )
       {
-         headers[ "User-Agent" ] = Settings.GetUserAgent( "curl/7.55.1" );
+         headers[ "User-Agent" ] = string.IsNullOrEmpty( AutoTranslationState.UserAgent ) ? "curl/7.55.1" : AutoTranslationState.UserAgent;
          headers[ "Accept" ] = "application/json";
          headers[ "Accept-Charset" ] = "UTF-8";
          headers[ "Authorization" ] = "Basic " + System.Convert.ToBase64String( System.Text.Encoding.ASCII.GetBytes( _username + ":" + _password ) );

+ 1 - 1
src/XUnity.AutoTranslator.Plugin.Core/Endpoints/Www/WwwEndpoint.cs

@@ -18,7 +18,7 @@ namespace XUnity.AutoTranslator.Plugin.Core.Endpoints.Www
 
       public abstract string FriendlyName { get; }
 
-      public abstract void Initialize( IConfiguration configuration, ServiceEndpointConfiguration servicePoints );
+      public abstract void Initialize( InitializationContext context );
 
       public abstract string GetServiceUrl( string untranslatedText, string from, string to );
 

+ 1 - 1
src/XUnity.AutoTranslator.Plugin.Core/Extensions/StringBuilderExtensions.cs

@@ -3,7 +3,7 @@ using System.Text;
 
 namespace XUnity.AutoTranslator.Plugin.Core.Extensions
 {
-   internal static class StringBuilderExtensions
+   public static class StringBuilderExtensions
    {
       public static bool EndsWithWhitespaceOrNewline( this StringBuilder builder )
       {

+ 1 - 1
src/XUnity.AutoTranslator.Plugin.Core/Logger.cs

@@ -16,7 +16,7 @@ namespace XUnity.AutoTranslator.Plugin.Core
          RespectSettings = true;
       }
 
-      public bool RespectSettings { get; protected set; }
+      protected internal bool RespectSettings { get; protected set; }
 
       public void Error( Exception e, string message )
       {

+ 1 - 1
src/XUnity.AutoTranslator.Plugin.Core/Web/ConnectionTrackingWebClient.cs

@@ -215,7 +215,7 @@ namespace XUnity.AutoTranslator.Plugin.Core.Web
       private bool is_busy;
       private IWebProxy proxy;
       private NameValueCollection queryString;
-      private WebHeaderCollection responseHeaders;
+      protected WebHeaderCollection responseHeaders;
       private static readonly string urlEncodedCType = "application/x-www-form-urlencoded";
 
       public event UnityDownloadStringCompletedEventHandler DownloadStringCompleted;

+ 2 - 2
src/XUnity.AutoTranslator.Plugin.Core/Web/ServiceEndpointConfiguration.cs → src/XUnity.AutoTranslator.Plugin.Core/Web/HttpSecurity.cs

@@ -8,11 +8,11 @@ using System.Text;
 
 namespace XUnity.AutoTranslator.Plugin.Core.Web
 {
-   public class ServiceEndpointConfiguration
+   public class HttpSecurity
    {
       public readonly HashSet<string> _hosts = new HashSet<string>();
 
-      public void EnableHttps( params string[] hosts )
+      public void EnableSslFor( params string[] hosts )
       {
          foreach( var host in hosts )
          {

+ 0 - 177
src/XUnity.AutoTranslator.Plugin.Core/Web/UnityWebClient.cs

@@ -1,177 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Reflection;
-using System.Text;
-using Harmony;
-using UnityEngine;
-using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http;
-using XUnity.AutoTranslator.Plugin.Core.Shim;
-
-namespace XUnity.AutoTranslator.Plugin.Core.Web
-{
-   public class UnityWebClient : ConnectionTrackingWebClient
-   {
-      private HttpEndpoint _httpEndpoint;
-
-      public UnityWebClient( HttpEndpoint endpoint )
-      {
-         _httpEndpoint = endpoint;
-         Encoding = Encoding.UTF8;
-      }
-
-      private void UnityWebClient_UploadStringCompleted( object sender, UnityUploadStringCompletedEventArgs ev )
-      {
-         UploadStringCompleted -= UnityWebClient_UploadStringCompleted;
-
-         var handle = ev.UserState as UnityWebResponse;
-
-         // obtain result, error, etc.
-         string text = null;
-         string error = null;
-
-         try
-         {
-            if( ev.Error == null )
-            {
-               text = ev.Result ?? string.Empty;
-            }
-            else
-            {
-               error = ev.Error.ToString();
-            }
-         }
-         catch( Exception e )
-         {
-            error = e.ToString();
-         }
-
-         handle.SetCompleted( text, error );
-      }
-
-      private void UnityWebClient_DownloadStringCompleted( object sender, UnityDownloadStringCompletedEventArgs ev )
-      {
-         DownloadStringCompleted -= UnityWebClient_DownloadStringCompleted;
-
-         var handle = ev.UserState as UnityWebResponse;
-
-         // obtain result, error, etc.
-         string text = null;
-         string error = null;
-
-         try
-         {
-            if( ev.Error == null )
-            {
-               text = ev.Result ?? string.Empty;
-            }
-            else
-            {
-               error = ev.Error.ToString();
-            }
-         }
-         catch( Exception e )
-         {
-            error = e.ToString();
-         }
-
-         handle.SetCompleted( text, error );
-      }
-
-      protected override WebRequest GetWebRequest( Uri address )
-      {
-         var request = base.GetWebRequest( address );
-         var httpRequest = request as HttpWebRequest;
-         if( httpRequest != null )
-         {
-            var cookies = _httpEndpoint.GetCookiesForNewRequest();
-            httpRequest.CookieContainer = cookies;
-         }
-         return request;
-      }
-
-      protected override WebResponse GetWebResponse( WebRequest request, IAsyncResult result )
-      {
-         WebResponse response = base.GetWebResponse( request, result );
-         WriteCookies( response );
-         return response;
-      }
-
-      protected override WebResponse GetWebResponse( WebRequest request )
-      {
-         WebResponse response = base.GetWebResponse( request );
-         WriteCookies( response );
-         return response;
-      }
-
-      private void WriteCookies( WebResponse r )
-      {
-         var response = r as HttpWebResponse;
-         if( response != null )
-         {
-            _httpEndpoint.StoreCookiesFromResponse( response );
-         }
-      }
-
-      public UnityWebResponse DownloadStringByUnityInstruction( Uri address )
-      {
-         var handle = new UnityWebResponse();
-
-         try
-         {
-            DownloadStringCompleted += UnityWebClient_DownloadStringCompleted;
-            DownloadStringAsync( address, handle );
-         }
-         catch
-         {
-            DownloadStringCompleted -= UnityWebClient_DownloadStringCompleted;
-            throw;
-         }
-
-         return handle;
-      }
-
-      public UnityWebResponse UploadStringByUnityInstruction( Uri address, string request )
-      {
-         var handle = new UnityWebResponse();
-
-         try
-         {
-            UploadStringCompleted += UnityWebClient_UploadStringCompleted;
-            UploadStringAsync( address, "POST", request, handle );
-         }
-         catch
-         {
-            UploadStringCompleted -= UnityWebClient_UploadStringCompleted;
-            throw;
-         }
-
-         return handle;
-      }
-   }
-
-   public class UnityWebResponse : CustomYieldInstructionShim
-   {
-      public void SetCompleted( string result, string error )
-      {
-         IsCompleted = true;
-
-         Result = result;
-         Error = error;
-      }
-
-      public override bool keepWaiting => !IsCompleted;
-
-      public string Result { get; set; }
-
-      public string Error { get; set; }
-
-      public bool IsCompleted { get; private set; } = false;
-
-      public bool Succeeded => Error == null;
-   }
-}

+ 128 - 0
src/XUnity.AutoTranslator.Plugin.Core/Web/XUnityWebClient.cs

@@ -0,0 +1,128 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Reflection;
+using System.Text;
+using Harmony;
+using UnityEngine;
+using XUnity.AutoTranslator.Plugin.Core.Endpoints.Http;
+
+namespace XUnity.AutoTranslator.Plugin.Core.Web
+{
+   public class XUnityWebClient : ConnectionTrackingWebClient
+   {
+      private HttpStatusCode? _responseCode;
+      private CookieCollection _responseCookies;
+
+      private CookieContainer _requestCookies;
+      private WebHeaderCollection _requestHeaders;
+
+      public XUnityWebClient()
+      {
+         Encoding = Encoding.UTF8;
+      }
+
+      private void UnityWebClient_UploadStringCompleted( object sender, UnityUploadStringCompletedEventArgs ev )
+      {
+         UploadStringCompleted -= UnityWebClient_UploadStringCompleted;
+
+         var handle = ev.UserState as XUnityWebResponse;
+
+         handle.SetCompleted( _responseCode.Value, ev.Result, responseHeaders, _responseCookies, ev.Error );
+      }
+
+      private void UnityWebClient_DownloadStringCompleted( object sender, UnityDownloadStringCompletedEventArgs ev )
+      {
+         DownloadStringCompleted -= UnityWebClient_DownloadStringCompleted;
+
+         var handle = ev.UserState as XUnityWebResponse;
+
+         handle.SetCompleted( _responseCode.Value, ev.Result, responseHeaders, _responseCookies, ev.Error );
+      }
+
+      protected override WebRequest GetWebRequest( Uri address )
+      {
+         var request = base.GetWebRequest( address );
+         SetRequestVariables( request );
+         return request;
+      }
+
+      protected override WebResponse GetWebResponse( WebRequest request, IAsyncResult result )
+      {
+         WebResponse response = base.GetWebResponse( request, result );
+         SetResponseVariables( response );
+         return response;
+      }
+
+      protected override WebResponse GetWebResponse( WebRequest request )
+      {
+         WebResponse response = base.GetWebResponse( request );
+         SetResponseVariables( response );
+         return response;
+      }
+
+      private void SetRequestVariables( WebRequest r )
+      {
+         var httpRequest = r as HttpWebRequest;
+         if( httpRequest != null )
+         {
+            if( _requestCookies != null )
+            {
+               httpRequest.CookieContainer = _requestCookies;
+            }
+            if( _requestHeaders != null )
+            {
+               Headers = _requestHeaders;
+            }
+         }
+      }
+
+      private void SetResponseVariables( WebResponse r )
+      {
+         var httpResponse = r as HttpWebResponse;
+         if( httpResponse != null )
+         {
+            _responseCode = httpResponse.StatusCode;
+            _responseCookies = httpResponse.Cookies;
+         }
+      }
+
+      public XUnityWebResponse Send( XUnityWebRequest request )
+      {
+         var handle = new XUnityWebResponse();
+
+         if( request.Data == null )
+         {
+            try
+            {
+               DownloadStringCompleted += UnityWebClient_DownloadStringCompleted;
+               DownloadStringAsync( request.Address, handle );
+            }
+            catch
+            {
+               DownloadStringCompleted -= UnityWebClient_DownloadStringCompleted;
+               throw;
+            }
+         }
+         else
+         {
+            try
+            {
+               UploadStringCompleted += UnityWebClient_UploadStringCompleted;
+               UploadStringAsync( request.Address, request.Method, request.Data, handle );
+            }
+            catch
+            {
+               UploadStringCompleted -= UnityWebClient_UploadStringCompleted;
+               throw;
+            }
+         }
+
+         return handle;
+      }
+   }
+}

+ 42 - 0
src/XUnity.AutoTranslator.Plugin.Core/Web/XUnityWebRequest.cs

@@ -0,0 +1,42 @@
+using System;
+using System.Net;
+
+namespace XUnity.AutoTranslator.Plugin.Core.Web
+{
+   public class XUnityWebRequest
+   {
+      private WebHeaderCollection _headers;
+
+      public XUnityWebRequest( string method, string address, string data )
+      {
+         Method = method;
+         Address = new Uri( address );
+         Data = data;
+      }
+
+      public XUnityWebRequest( string address )
+      {
+         Method = "GET";
+         Address = new Uri( address );
+      }
+
+      public string Method { get; private set; }
+      public Uri Address { get; private set; }
+      public string Data { get; private set; }
+
+      public CookieContainer Cookies { get; set; }
+      public WebHeaderCollection Headers
+      {
+         get
+         {
+            if( _headers == null ) _headers = new WebHeaderCollection();
+
+            return _headers;
+         }
+         set
+         {
+            _headers = value;
+         }
+      }
+   }
+}

+ 29 - 0
src/XUnity.AutoTranslator.Plugin.Core/Web/XUnityWebResponse.cs

@@ -0,0 +1,29 @@
+using System;
+using System.Net;
+using XUnity.AutoTranslator.Plugin.Core.Shim;
+
+namespace XUnity.AutoTranslator.Plugin.Core.Web
+{
+   public class XUnityWebResponse : CustomYieldInstructionShim
+   {
+      public void SetCompleted( HttpStatusCode code, string result, WebHeaderCollection headers, CookieCollection newCookies, Exception error )
+      {
+         IsCompleted = true;
+
+         Code = code;
+         Result = result;
+         Headers = headers;
+         NewCookies = newCookies;
+         Error = error;
+      }
+
+      public HttpStatusCode Code { get; set; }
+      public string Result { get; private set; }
+      public WebHeaderCollection Headers { get; private set; }
+      public CookieCollection NewCookies { get; private set; }
+      public Exception Error { get; private set; }
+
+      public override bool keepWaiting => !IsCompleted;
+      internal bool IsCompleted { get; private set; } = false;
+   }
+}

+ 1 - 1
src/XUnity.AutoTranslator.Plugin.IPA/XUnity.AutoTranslator.Plugin.IPA.csproj

@@ -28,7 +28,7 @@
       <ItemGroup>
          <VersionNumber Include="$([System.Text.RegularExpressions.Regex]::Replace(&quot;%(Targets.Version)&quot;, &quot;^(.+?)(\.0+)$&quot;, &quot;$1&quot;))" />
       </ItemGroup>
-      <Exec Command="if $(ConfigurationName) == Release (&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)ExIni.dll&quot; &quot;$(SolutionDir)dist\IPA\Plugins\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)0Harmony.dll&quot; &quot;$(SolutionDir)dist\IPA\Plugins\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)XUnity.AutoTranslator.Plugin.Core.dll&quot; &quot;$(SolutionDir)dist\IPA\Plugins\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)$(TargetName)$(TargetExt)&quot; &quot;$(SolutionDir)dist\IPA\Plugins\&quot;&#xD;&#xA;   COPY /Y &quot;$(SolutionDir)README.md&quot; &quot;$(SolutionDir)dist\IPA\Plugins\README (AutoTranslator).md&quot;&#xD;&#xA;   powershell Compress-Archive -Path '$(SolutionDir)dist\IPA\Plugins' -DestinationPath '$(SolutionDir)dist\IPA\XUnity.AutoTranslator-IPA-@(VersionNumber).zip' -Force)&#xD;&#xA;)" />
+      <Exec Command="if $(ConfigurationName) == Release (&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)ExIni.dll&quot; &quot;$(SolutionDir)dist\IPA\Plugins\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)0Harmony.dll&quot; &quot;$(SolutionDir)dist\IPA\Plugins\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)XUnity.AutoTranslator.Plugin.Core.dll&quot; &quot;$(SolutionDir)dist\IPA\Plugins\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)$(TargetName)$(TargetExt)&quot; &quot;$(SolutionDir)dist\IPA\Plugins\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(SolutionDir)src\XUnity.AutoTranslator.Plugin.Lec\bin\x86\Release\net35\XUnity.AutoTranslator.Plugin.Lec.exe&quot; &quot;$(SolutionDir)dist\IPA\Plugins\&quot;&#xD;&#xA;   COPY /Y &quot;$(SolutionDir)README.md&quot; &quot;$(SolutionDir)dist\IPA\Plugins\README (AutoTranslator).md&quot;&#xD;&#xA;   powershell Compress-Archive -Path '$(SolutionDir)dist\IPA\Plugins' -DestinationPath '$(SolutionDir)dist\IPA\XUnity.AutoTranslator-IPA-@(VersionNumber).zip' -Force)&#xD;&#xA;)" />
    </Target>
 
 </Project>

+ 8 - 0
src/XUnity.AutoTranslator.Plugin.Lec/Program.cs

@@ -11,6 +11,14 @@ namespace XUnity.AutoTranslator.Plugin.Lec
       {
          try
          {
+            if( args.Length == 0 )
+            {
+               Console.WriteLine( "This program is automatically run during a game session if LEC is selected, and will be automatically stopped afterwards. This program cannot be run independently." );
+               Console.WriteLine( "Press any key to exit." );
+               Console.ReadKey();
+               return;
+            }
+
             var powerTranslatorPathPayload = args[ 0 ];
             var powerTranslatorPath = Encoding.UTF8.GetString( Convert.FromBase64String( powerTranslatorPathPayload ) );
             var dllPath = Path.Combine( powerTranslatorPath, @"Nova\JaEn\EngineDll_je.dll" );

+ 1 - 2
src/XUnity.AutoTranslator.Plugin.Lec/Properties/launchSettings.json

@@ -1,8 +1,7 @@
 {
   "profiles": {
     "XUnity.AutoTranslator.Plugin.Lec": {
-      "commandName": "Project",
-      "commandLineArgs": "QzpcUHJvZ3JhbSBGaWxlcyAoeDg2KVxQb3dlciBUcmFuc2xhdG9yIDE1"
+      "commandName": "Project"
     }
   }
 }

+ 1 - 1
src/XUnity.AutoTranslator.Plugin.UnityInjector/XUnity.AutoTranslator.Plugin.UnityInjector.csproj

@@ -28,7 +28,7 @@
       <ItemGroup>
          <VersionNumber Include="$([System.Text.RegularExpressions.Regex]::Replace(&quot;%(Targets.Version)&quot;, &quot;^(.+?)(\.0+)$&quot;, &quot;$1&quot;))" />
       </ItemGroup>
-      <Exec Command="if $(ConfigurationName) == Release (&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)ExIni.dll&quot; &quot;$(SolutionDir)dist\UnityInjector\UnityInjector\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)0Harmony.dll&quot; &quot;$(SolutionDir)dist\UnityInjector\UnityInjector\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)XUnity.AutoTranslator.Plugin.Core.dll&quot; &quot;$(SolutionDir)dist\UnityInjector\UnityInjector\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)$(TargetName)$(TargetExt)&quot; &quot;$(SolutionDir)dist\UnityInjector\UnityInjector\&quot;&#xD;&#xA;   COPY /Y &quot;$(SolutionDir)README.md&quot; &quot;$(SolutionDir)dist\UnityInjector\UnityInjector\README (AutoTranslator).md&quot;&#xD;&#xA;   powershell Compress-Archive -Path '$(SolutionDir)dist\UnityInjector\UnityInjector' -DestinationPath '$(SolutionDir)dist\UnityInjector\XUnity.AutoTranslator-UnityInjector-@(VersionNumber).zip' -Force)&#xD;&#xA;)" />
+      <Exec Command="if $(ConfigurationName) == Release (&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)ExIni.dll&quot; &quot;$(SolutionDir)dist\UnityInjector\UnityInjector\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)0Harmony.dll&quot; &quot;$(SolutionDir)dist\UnityInjector\UnityInjector\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)XUnity.AutoTranslator.Plugin.Core.dll&quot; &quot;$(SolutionDir)dist\UnityInjector\UnityInjector\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(TargetDir)$(TargetName)$(TargetExt)&quot; &quot;$(SolutionDir)dist\UnityInjector\UnityInjector\&quot;&#xD;&#xA;   XCOPY /Y /I &quot;$(SolutionDir)src\XUnity.AutoTranslator.Plugin.Lec\bin\x86\Release\net35\XUnity.AutoTranslator.Plugin.Lec.exe&quot; &quot;$(SolutionDir)dist\UnityInjector\UnityInjector\&quot;&#xD;&#xA;   COPY /Y &quot;$(SolutionDir)README.md&quot; &quot;$(SolutionDir)dist\UnityInjector\UnityInjector\README (AutoTranslator).md&quot;&#xD;&#xA;   powershell Compress-Archive -Path '$(SolutionDir)dist\UnityInjector\UnityInjector' -DestinationPath '$(SolutionDir)dist\UnityInjector\XUnity.AutoTranslator-UnityInjector-@(VersionNumber).zip' -Force)&#xD;&#xA;)" />
    </Target>
 
 </Project>

+ 3 - 2
src/XUnity.AutoTranslator.Setup/Program.cs

@@ -29,6 +29,7 @@ namespace XUnity.AutoTranslator.Setup
 
          var reiPath = Path.Combine( gamePath, "ReiPatcher" );
          var patchesPath = Path.Combine( reiPath, "Patches" );
+         var autoTranslatorPath = Path.Combine( gamePath, "AutoTranslator" );
 
          // lets add any missing files
          AddFile( Path.Combine( reiPath, "ExIni.dll" ), Resources.ExIni );
@@ -39,14 +40,14 @@ namespace XUnity.AutoTranslator.Setup
          AddFile( Path.Combine( reiPath, "Mono.Cecil.Rocks.dll" ), Resources.Mono_Cecil_Rocks );
          AddFile( Path.Combine( reiPath, "ReiPatcher.exe" ), Resources.ReiPatcher );
          AddFile( Path.Combine( patchesPath, "XUnity.AutoTranslator.Patcher.dll" ), Resources.XUnity_AutoTranslator_Patcher, true );
-
+         AddFile( Path.Combine( autoTranslatorPath, "XUnity.AutoTranslator.Plugin.Lec.exe" ), Resources.XUnity_AutoTranslator_Plugin_Lec, true );
 
          foreach( var launcher in launchers )
          {
             var managedDir = Path.Combine( gamePath, launcher.Data.Name, "Managed" );
             AddFile( Path.Combine( managedDir, "0Harmony.dll" ), Resources._0Harmony );
             AddFile( Path.Combine( managedDir, "ExIni.dll" ), Resources.ExIni );
-            AddFile( Path.Combine( managedDir, "ReiPatcher.exe" ), Resources.ReiPatcher ); // needed because file is modified by attribute in ReiPatcher... QQ
+            AddFile( Path.Combine( managedDir, "ReiPatcher.exe" ), Resources.ReiPatcher );
             AddFile( Path.Combine( managedDir, "XUnity.AutoTranslator.Plugin.Core.dll" ), Resources.XUnity_AutoTranslator_Plugin_Core, true );
 
             // create an .ini file for each launcher, if it does not already exist

+ 10 - 10
src/XUnity.AutoTranslator.Setup/Properties/Resources.Designer.cs

@@ -80,16 +80,6 @@ namespace XUnity.AutoTranslator.Setup.Properties {
             }
         }
         
-        /// <summary>
-        ///   Looks up a localized resource of type System.Byte[].
-        /// </summary>
-        internal static byte[] Jurassic {
-            get {
-                object obj = ResourceManager.GetObject("Jurassic", resourceCulture);
-                return ((byte[])(obj));
-            }
-        }
-        
         /// <summary>
         ///   Looks up a localized resource of type System.Byte[].
         /// </summary>
@@ -169,5 +159,15 @@ namespace XUnity.AutoTranslator.Setup.Properties {
                 return ((byte[])(obj));
             }
         }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Byte[].
+        /// </summary>
+        internal static byte[] XUnity_AutoTranslator_Plugin_Lec {
+            get {
+                object obj = ResourceManager.GetObject("XUnity_AutoTranslator_Plugin_Lec", resourceCulture);
+                return ((byte[])(obj));
+            }
+        }
     }
 }

+ 4 - 1
src/XUnity.AutoTranslator.Setup/Properties/Resources.resx

@@ -145,7 +145,10 @@
   <data name="XUnity_AutoTranslator_Plugin_Core" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\..\XUnity.AutoTranslator.Plugin.Core\bin\Release\net35\XUnity.AutoTranslator.Plugin.Core.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </data>
+  <data name="XUnity_AutoTranslator_Plugin_Lec" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\..\XUnity.AutoTranslator.Plugin.Lec\bin\x86\Release\net35\XUnity.AutoTranslator.Plugin.Lec.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
   <data name="_0Harmony" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\..\..\libs\0Harmony.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </data>
-</root>
+</root>