| @@ -24,7 +24,7 @@ jobs: | |||||
| - name: Setup Python | - name: Setup Python | ||||
| uses: actions/setup-python@v4 | uses: actions/setup-python@v4 | ||||
| with: | with: | ||||
| python-version: '3.10' | |||||
| python-version: '3.9' | |||||
| - name: Pip Install paramiko | - name: Pip Install paramiko | ||||
| run: pip install paramiko | run: pip install paramiko | ||||
| @@ -118,7 +118,7 @@ public: | |||||
| [[nodiscard]] virtual std::pair<int64_t, std::string> GetMessage() = 0; | [[nodiscard]] virtual std::pair<int64_t, std::string> GetMessage() = 0; | ||||
| // 等待下一帧 | // 等待下一帧 | ||||
| virtual std::future<bool> Wait() = 0; | |||||
| virtual bool Wait() = 0; | |||||
| // 获取视野内可见的学生/捣蛋鬼的信息 | // 获取视野内可见的学生/捣蛋鬼的信息 | ||||
| [[nodiscard]] virtual std::vector<std::shared_ptr<const THUAI6::Student>> GetStudents() const = 0; | [[nodiscard]] virtual std::vector<std::shared_ptr<const THUAI6::Student>> GetStudents() const = 0; | ||||
| @@ -242,7 +242,7 @@ public: | |||||
| [[nodiscard]] bool HaveMessage() override; | [[nodiscard]] bool HaveMessage() override; | ||||
| [[nodiscard]] std::pair<int64_t, std::string> GetMessage() override; | [[nodiscard]] std::pair<int64_t, std::string> GetMessage() override; | ||||
| std::future<bool> Wait() override; | |||||
| bool Wait() override; | |||||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Student>> GetStudents() const override; | [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Student>> GetStudents() const override; | ||||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Tricker>> GetTrickers() const override; | [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Tricker>> GetTrickers() const override; | ||||
| @@ -330,7 +330,7 @@ public: | |||||
| [[nodiscard]] bool HaveMessage() override; | [[nodiscard]] bool HaveMessage() override; | ||||
| [[nodiscard]] std::pair<int64_t, std::string> GetMessage() override; | [[nodiscard]] std::pair<int64_t, std::string> GetMessage() override; | ||||
| std::future<bool> Wait() override; | |||||
| bool Wait() override; | |||||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Student>> GetStudents() const override; | [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Student>> GetStudents() const override; | ||||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Tricker>> GetTrickers() const override; | [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Tricker>> GetTrickers() const override; | ||||
| @@ -410,7 +410,7 @@ public: | |||||
| [[nodiscard]] bool HaveMessage() override; | [[nodiscard]] bool HaveMessage() override; | ||||
| [[nodiscard]] std::pair<int64_t, std::string> GetMessage() override; | [[nodiscard]] std::pair<int64_t, std::string> GetMessage() override; | ||||
| std::future<bool> Wait() override; | |||||
| bool Wait() override; | |||||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Student>> GetStudents() const override; | [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Student>> GetStudents() const override; | ||||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Tricker>> GetTrickers() const override; | [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Tricker>> GetTrickers() const override; | ||||
| @@ -483,7 +483,7 @@ public: | |||||
| [[nodiscard]] bool HaveMessage() override; | [[nodiscard]] bool HaveMessage() override; | ||||
| [[nodiscard]] std::pair<int64_t, std::string> GetMessage() override; | [[nodiscard]] std::pair<int64_t, std::string> GetMessage() override; | ||||
| std::future<bool> Wait() override; | |||||
| bool Wait() override; | |||||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Student>> GetStudents() const override; | [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Student>> GetStudents() const override; | ||||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Tricker>> GetTrickers() const override; | [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Tricker>> GetTrickers() const override; | ||||
| @@ -217,24 +217,20 @@ std::pair<int64_t, std::string> TrickerAPI::GetMessage() | |||||
| return logic.GetMessage(); | return logic.GetMessage(); | ||||
| } | } | ||||
| std::future<bool> StudentAPI::Wait() | |||||
| bool StudentAPI::Wait() | |||||
| { | { | ||||
| if (logic.GetCounter() == -1) | if (logic.GetCounter() == -1) | ||||
| return std::async(std::launch::async, [this]() | |||||
| { return false; }); | |||||
| return false; | |||||
| else | else | ||||
| return std::async(std::launch::async, [this]() | |||||
| { return logic.WaitThread(); }); | |||||
| return logic.WaitThread(); | |||||
| } | } | ||||
| std::future<bool> TrickerAPI::Wait() | |||||
| bool TrickerAPI::Wait() | |||||
| { | { | ||||
| if (logic.GetCounter() == -1) | if (logic.GetCounter() == -1) | ||||
| return std::async(std::launch::async, [this]() | |||||
| { return false; }); | |||||
| return false; | |||||
| else | else | ||||
| return std::async(std::launch::async, [this]() | |||||
| { return logic.WaitThread(); }); | |||||
| return logic.WaitThread(); | |||||
| } | } | ||||
| std::vector<std::shared_ptr<const THUAI6::Tricker>> StudentAPI::GetTrickers() const | std::vector<std::shared_ptr<const THUAI6::Tricker>> StudentAPI::GetTrickers() const | ||||
| @@ -403,26 +403,22 @@ std::pair<int64_t, std::string> TrickerDebugAPI::GetMessage() | |||||
| return result; | return result; | ||||
| } | } | ||||
| std::future<bool> StudentDebugAPI::Wait() | |||||
| bool StudentDebugAPI::Wait() | |||||
| { | { | ||||
| logger->info("Wait: called at {}ms", Time::TimeSinceStart(startPoint)); | logger->info("Wait: called at {}ms", Time::TimeSinceStart(startPoint)); | ||||
| if (logic.GetCounter() == -1) | if (logic.GetCounter() == -1) | ||||
| return std::async(std::launch::async, []() | |||||
| { return false; }); | |||||
| return false; | |||||
| else | else | ||||
| return std::async(std::launch::async, [this]() | |||||
| { return logic.WaitThread(); }); | |||||
| return logic.WaitThread(); | |||||
| } | } | ||||
| std::future<bool> TrickerDebugAPI::Wait() | |||||
| bool TrickerDebugAPI::Wait() | |||||
| { | { | ||||
| logger->info("Wait: called at {}ms", Time::TimeSinceStart(startPoint)); | logger->info("Wait: called at {}ms", Time::TimeSinceStart(startPoint)); | ||||
| if (logic.GetCounter() == -1) | if (logic.GetCounter() == -1) | ||||
| return std::async(std::launch::async, []() | |||||
| { return false; }); | |||||
| return false; | |||||
| else | else | ||||
| return std::async(std::launch::async, [this]() | |||||
| { return logic.WaitThread(); }); | |||||
| return logic.WaitThread(); | |||||
| } | } | ||||
| std::vector<std::shared_ptr<const THUAI6::Tricker>> StudentDebugAPI::GetTrickers() const | std::vector<std::shared_ptr<const THUAI6::Tricker>> StudentDebugAPI::GetTrickers() const | ||||
| @@ -43,7 +43,7 @@ class AI(IAI): | |||||
| self.__playerID = pID | self.__playerID = pID | ||||
| def StudentPlay(self, api: IStudentAPI) -> None: | def StudentPlay(self, api: IStudentAPI) -> None: | ||||
| #公共操作 | |||||
| # 公共操作 | |||||
| if self.__playerID == 0: | if self.__playerID == 0: | ||||
| # 玩家0执行操作 | # 玩家0执行操作 | ||||
| return | return | ||||
| @@ -56,8 +56,8 @@ class AI(IAI): | |||||
| elif self.__playerID == 3: | elif self.__playerID == 3: | ||||
| # 玩家3执行操作 | # 玩家3执行操作 | ||||
| return | return | ||||
| #可以写成if self.__playerID<2之类的写法 | |||||
| #公共操作 | |||||
| # 可以写成if self.__playerID<2之类的写法 | |||||
| # 公共操作 | |||||
| return | return | ||||
| def TrickerPlay(self, api: ITrickerAPI) -> None: | def TrickerPlay(self, api: ITrickerAPI) -> None: | ||||
| @@ -79,11 +79,11 @@ class StudentAPI(IStudentAPI, IGameTimer): | |||||
| # 等待下一帧 | # 等待下一帧 | ||||
| def Wait(self) -> Future[bool]: | |||||
| def Wait(self) -> bool: | |||||
| if self.__logic.GetCounter() == -1: | if self.__logic.GetCounter() == -1: | ||||
| return self.__pool.submit(lambda: False) | |||||
| return False | |||||
| else: | else: | ||||
| return self.__pool.submit(self.__logic.WaitThread) | |||||
| return self.__logic.WaitThread() | |||||
| # 获取各类游戏中的消息 | # 获取各类游戏中的消息 | ||||
| @@ -252,11 +252,11 @@ class TrickerAPI(ITrickerAPI, IGameTimer): | |||||
| # 等待下一帧 | # 等待下一帧 | ||||
| def Wait(self) -> Future[bool]: | |||||
| def Wait(self) -> bool: | |||||
| if self.__logic.GetCounter() == -1: | if self.__logic.GetCounter() == -1: | ||||
| return self.__pool.submit(lambda: False) | |||||
| return False | |||||
| else: | else: | ||||
| return self.__pool.submit(self.__logic.WaitThread) | |||||
| return self.__logic.WaitThread() | |||||
| # 获取各类游戏中的消息 | # 获取各类游戏中的消息 | ||||
| @@ -249,13 +249,13 @@ class StudentDebugAPI(IStudentAPI, IGameTimer): | |||||
| # 等待下一帧 | # 等待下一帧 | ||||
| def Wait(self) -> Future[bool]: | |||||
| def Wait(self) -> bool: | |||||
| self.__logger.info( | self.__logger.info( | ||||
| f"Wait: called at {self.__GetTime()}ms") | f"Wait: called at {self.__GetTime()}ms") | ||||
| if self.__logic.GetCounter() == -1: | if self.__logic.GetCounter() == -1: | ||||
| return self.__pool.submit(lambda: False) | |||||
| return False | |||||
| else: | else: | ||||
| return self.__pool.submit(self.__logic.WaitThread) | |||||
| return self.__logic.WaitThread() | |||||
| # 获取各类游戏中的消息 | # 获取各类游戏中的消息 | ||||
| @@ -701,13 +701,13 @@ class TrickerDebugAPI(ITrickerAPI, IGameTimer): | |||||
| # 等待下一帧 | # 等待下一帧 | ||||
| def Wait(self) -> Future[bool]: | |||||
| def Wait(self) -> bool: | |||||
| self.__logger.info( | self.__logger.info( | ||||
| f"Wait: called at {self.__GetTime()}ms") | f"Wait: called at {self.__GetTime()}ms") | ||||
| if self.__logic.GetCounter() == -1: | if self.__logic.GetCounter() == -1: | ||||
| return self.__pool.submit(lambda: False) | |||||
| return False | |||||
| else: | else: | ||||
| return self.__pool.submit(self.__logic.WaitThread) | |||||
| return self.__logic.WaitThread() | |||||
| # 获取各类游戏中的消息 | # 获取各类游戏中的消息 | ||||
| @@ -245,7 +245,7 @@ class IAPI(metaclass=ABCMeta): | |||||
| # 等待下一帧 | # 等待下一帧 | ||||
| @abstractmethod | @abstractmethod | ||||
| def Wait(self) -> Future[bool]: | |||||
| def Wait(self) -> bool: | |||||
| pass | pass | ||||
| # 获取各类游戏中的消息 | # 获取各类游戏中的消息 | ||||
| @@ -6,11 +6,9 @@ | |||||
| <Nullable>enable</Nullable> | <Nullable>enable</Nullable> | ||||
| <UseWPF>true</UseWPF> | <UseWPF>true</UseWPF> | ||||
| <UseWindowsForms>true</UseWindowsForms> | <UseWindowsForms>true</UseWindowsForms> | ||||
| <AppHostDotNetRoot>dotNetRuntime</AppHostDotNetRoot> | |||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <PackageReference Include="dotnetCampus.AppHost" Version="1.0.0-alpha10" /> | |||||
| <PackageReference Include="ICSharpCode.SharpZipLib.dll" Version="0.85.4.369" /> | <PackageReference Include="ICSharpCode.SharpZipLib.dll" Version="0.85.4.369" /> | ||||
| <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" /> | <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" /> | ||||
| <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> | <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> | ||||
| @@ -691,12 +691,14 @@ namespace Downloader | |||||
| catch (CosClientException clientEx) | catch (CosClientException clientEx) | ||||
| { | { | ||||
| // 请求失败 | // 请求失败 | ||||
| MessageBox.Show("网络错误"); | |||||
| Console.WriteLine("CosClientException: " + clientEx.ToString() + Environment.NewLine); | Console.WriteLine("CosClientException: " + clientEx.ToString() + Environment.NewLine); | ||||
| return; | return; | ||||
| } | } | ||||
| catch (CosServerException serverEx) | catch (CosServerException serverEx) | ||||
| { | { | ||||
| // 请求失败 | // 请求失败 | ||||
| MessageBox.Show("网络错误"); | |||||
| Console.WriteLine("CosClientException: " + serverEx.ToString() + Environment.NewLine); | Console.WriteLine("CosClientException: " + serverEx.ToString() + Environment.NewLine); | ||||
| return; | return; | ||||
| } | } | ||||
| @@ -1195,9 +1197,11 @@ namespace Downloader | |||||
| public static int CheckSelfVersion() | public static int CheckSelfVersion() | ||||
| { | { | ||||
| string keyHead = "Installer/"; | |||||
| Tencent_cos_download downloader = new Tencent_cos_download(); | Tencent_cos_download downloader = new Tencent_cos_download(); | ||||
| string hashName = "installerHash.json"; | string hashName = "installerHash.json"; | ||||
| string dir = Directory.GetCurrentDirectory(); | string dir = Directory.GetCurrentDirectory(); | ||||
| int result = 0; | |||||
| try | try | ||||
| { | { | ||||
| if (File.Exists(System.IO.Path.Combine(dir, hashName))) | if (File.Exists(System.IO.Path.Combine(dir, hashName))) | ||||
| @@ -1213,28 +1217,42 @@ namespace Downloader | |||||
| json = r.ReadToEnd(); | json = r.ReadToEnd(); | ||||
| json = json.Replace("\r", string.Empty).Replace("\n", string.Empty); | json = json.Replace("\r", string.Empty).Replace("\n", string.Empty); | ||||
| Dictionary<string, string> jsonDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json); | Dictionary<string, string> jsonDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json); | ||||
| string md5 = ""; | |||||
| List<string> awaitUpdate = new List<string>(); | |||||
| if (jsonDict != null) | if (jsonDict != null) | ||||
| { | { | ||||
| if (jsonDict.ContainsKey("InstallerUpdater.exe")) | |||||
| { | |||||
| string updaterHash = GetFileMd5Hash(System.IO.Path.Combine(dir, "InstallerUpdater.exe")); | |||||
| if (updaterHash != null && !jsonDict["InstallerUpdater.exe"].Equals(updaterHash)) | |||||
| downloader.download(System.IO.Path.Combine(dir, "InstallerUpdater.exe"), "InstallerUpdater.exe"); | |||||
| } | |||||
| else | |||||
| return -1; | |||||
| if (jsonDict.ContainsKey("Installer.exe")) | |||||
| foreach (KeyValuePair<string, string> pair in jsonDict) | |||||
| { | { | ||||
| string selfHash = GetFileMd5Hash(System.IO.Path.Combine(dir, "Installer.exe")); | |||||
| if (selfHash != null && !jsonDict["Installer.exe"].Equals(selfHash)) | |||||
| return 1; | |||||
| md5 = GetFileMd5Hash(System.IO.Path.Combine(dir, pair.Key)); | |||||
| if (md5.Length == 0) // 文档不存在 | |||||
| { | |||||
| downloader.download(System.IO.Path.Combine(dir, pair.Key), keyHead + pair.Key); | |||||
| } | |||||
| else if (md5.Equals("conflict")) | |||||
| { | |||||
| MessageBox.Show($"检查{pair.Key}更新时遇到问题,请反馈", "读取出错", MessageBoxButton.OK, MessageBoxImage.Error); | |||||
| } | |||||
| else if (md5 != pair.Value) // MD5不匹配 | |||||
| { | |||||
| if (pair.Key.Substring(0, 12).Equals("InstallerUpd")) | |||||
| { | |||||
| File.Delete(System.IO.Path.Combine(dir, pair.Key)); | |||||
| downloader.download(System.IO.Path.Combine(dir, pair.Key), keyHead + pair.Key); | |||||
| } | |||||
| else | |||||
| { | |||||
| result = 1; | |||||
| awaitUpdate.Append(pair.Key); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| else | |||||
| return -1; | |||||
| } | } | ||||
| else | else | ||||
| return -1; | return -1; | ||||
| return 0; | |||||
| string Contentjson = JsonConvert.SerializeObject(awaitUpdate); | |||||
| Contentjson = Contentjson.Replace("\r", String.Empty).Replace("\n", String.Empty).Replace(@"\\", "/"); | |||||
| File.WriteAllText(@System.IO.Path.Combine(dir, "updateList.json"), Contentjson); | |||||
| return result; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -33,7 +33,7 @@ namespace starter.viewmodel.settings | |||||
| public SettingsViewModel() | public SettingsViewModel() | ||||
| { | { | ||||
| //Program.Tencent_cos_download.UpdateHash(); | |||||
| Program.Tencent_cos_download.UpdateHash(); | |||||
| Status = SettingsModel.Status.working; | Status = SettingsModel.Status.working; | ||||
| @@ -152,6 +152,13 @@ namespace starter.viewmodel.settings | |||||
| if (asyncUpdater.CancellationPending) | if (asyncUpdater.CancellationPending) | ||||
| { | { | ||||
| e.Cancel = true; | e.Cancel = true; | ||||
| MessageBox.Show("下载取消"); | |||||
| if (e.Argument.ToString().Equals("Manual")) | |||||
| { | |||||
| Status = SettingsModel.Status.menu; | |||||
| } | |||||
| else | |||||
| Status = SettingsModel.Status.login; | |||||
| return; | return; | ||||
| } | } | ||||
| else | else | ||||
| @@ -5,14 +5,12 @@ | |||||
| <TargetFramework>net6.0-windows</TargetFramework> | <TargetFramework>net6.0-windows</TargetFramework> | ||||
| <Nullable>enable</Nullable> | <Nullable>enable</Nullable> | ||||
| <UseWPF>true</UseWPF> | <UseWPF>true</UseWPF> | ||||
| <AppHostDotNetRoot>dotNetRuntime</AppHostDotNetRoot> | |||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <PackageReference Include="dotnetCampus.AppHost" Version="1.0.0-alpha10" /> | |||||
| <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> | <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> | ||||
| <PackageReference Include="Tencent.QCloud.Cos.Sdk" Version="5.4.34"> | <PackageReference Include="Tencent.QCloud.Cos.Sdk" Version="5.4.34"> | ||||
| <TreatAsUsed>true</TreatAsUsed> | |||||
| <TreatAsUsed>true</TreatAsUsed> | |||||
| </PackageReference> | </PackageReference> | ||||
| </ItemGroup> | </ItemGroup> | ||||
| @@ -28,6 +28,7 @@ namespace InstallerUpdater | |||||
| public MainWindow() | public MainWindow() | ||||
| { | { | ||||
| InitializeComponent(); | InitializeComponent(); | ||||
| MessageBox.Show("这是旧版"); | |||||
| asyncDownloader.DoWork += AsyncDownloader_DoWork; | asyncDownloader.DoWork += AsyncDownloader_DoWork; | ||||
| asyncDownloader.RunWorkerCompleted += AsyncDownloader_RunWorkerCompleted; | asyncDownloader.RunWorkerCompleted += AsyncDownloader_RunWorkerCompleted; | ||||
| if (asyncDownloader.IsBusy) | if (asyncDownloader.IsBusy) | ||||
| @@ -19,14 +19,22 @@ namespace Program | |||||
| public static string Dir = Directory.GetCurrentDirectory(); | public static string Dir = Directory.GetCurrentDirectory(); | ||||
| public static string InstallerName = "Installer.exe"; | public static string InstallerName = "Installer.exe"; | ||||
| public static string jsonKey = "installerHash.json"; | public static string jsonKey = "installerHash.json"; | ||||
| public static string KeyHead = "Installer/"; | |||||
| public static bool UpdateInstaller() | public static bool UpdateInstaller() | ||||
| { | { | ||||
| string json; | |||||
| try | try | ||||
| { | { | ||||
| download(Path.Combine(Dir, "newInstaller.exe"), InstallerName); | |||||
| File.Delete(Path.Combine(Dir, InstallerName)); | |||||
| File.Move(Path.Combine(Dir, "newInstaller.exe"), Path.Combine(Dir, InstallerName)); | |||||
| using (StreamReader r = new StreamReader(System.IO.Path.Combine(Dir, "updateList.json"))) | |||||
| json = r.ReadToEnd(); | |||||
| json = json.Replace("\r", string.Empty).Replace("\n", string.Empty); | |||||
| List<string> jsonList = JsonConvert.DeserializeObject<List<string>>(json); | |||||
| foreach (string todo in jsonList) | |||||
| { | |||||
| File.Delete(Path.Combine(Dir, todo)); | |||||
| download(Path.Combine(Dir, todo), KeyHead + todo); | |||||
| } | |||||
| } | } | ||||
| catch | catch | ||||
| { | { | ||||