| @@ -7,7 +7,7 @@ name: "upload_COS" | |||
| on: | |||
| push: | |||
| branches: [ main, dev ] | |||
| branches: [ main ] | |||
| jobs: | |||
| client_build: | |||
| @@ -137,7 +137,6 @@ jobs: | |||
| - name: Remove Files | |||
| run: | | |||
| rm ./THUAI6/hash.json | |||
| rm ./THUAI6/win/win64/PresentationCore.dll | |||
| rm ./THUAI6/win/win64/PresentationFramework.dll | |||
| @@ -1,5 +1,5 @@ | |||
| @echo off | |||
| .\win64\Server.exe --port 8888 --studentCount 1 --trickerCount 1 --gameTimeInSecond 600 --fileName video | |||
| .\win64\Server.exe --port 8888 --studentCount 4 --trickerCount 1 --gameTimeInSecond 600 --fileName video | |||
| pause | |||
| @@ -3,4 +3,5 @@ | |||
| ./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 0 -d -o & | |||
| ./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 1 -d -o & | |||
| ./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 2 -d -o & | |||
| ./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 3 -d -o & | |||
| ./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 3 -d -o & | |||
| ./CAPI/cpp/build/capi -I 127.0.0.1 -P 8888 -p 4 -d -o & | |||
| @@ -3,4 +3,5 @@ | |||
| python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 0 -d -o & | |||
| python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 1 -d -o & | |||
| python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 2 -d -o & | |||
| python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 3 -d -o & | |||
| python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 3 -d -o & | |||
| python ./CAPI/python/PyAPI/main.py -I 127.0.0.1 -P 8888 -p 4 -d -o & | |||
| @@ -90,6 +90,7 @@ start python .\CAPI\python\PyAPI\main.py -I 127.0.0.1 -P 8888 -p 0 -d -o -w | |||
| `-P`为服务器端口,一般为8888 | |||
| `-p`为玩家id,一般学生为0~3,捣蛋鬼为4 | |||
| - 请注意学生序号要从0开始,如果学生数量为n,不应当出现id大于等于n的学生 | |||
| `-d`为保存Debug日志文件(在`/logs/`下) | |||
| @@ -116,6 +117,7 @@ start python .\CAPI\python\PyAPI\main.py -I 127.0.0.1 -P 8888 -p 0 -d -o -w | |||
| `--characterID`为玩家id | |||
| - 学生取值为0,1,2,3,捣蛋鬼取值为4,characterID > 2023则是观战模式 | |||
| - 请注意学生序号要从0开始,如果学生数量为n,不应当出现id大于等于n的学生 | |||
| - 应当使`RunGUIClient.cmd`与 `RunPython.cmd`(或`RunCpp.cmd`)中学生、捣蛋鬼数量之和符合`RunServer.cmd`的要求 | |||
| - 如果不启动`RunPython.cmd`(或`RunCpp.cmd`),则`RunGUIClient.cmd`中学生、捣蛋鬼数量应当符合`RunServer.cmd`的要求 | |||
| @@ -40,7 +40,8 @@ | |||
| <Button Grid.Row="3" Grid.Column="6" Name="GetRouteBtn" Content="选择文件夹" Command="{Binding ClickBrowseCommand}" Visibility="{Binding RouteBoxVis}" /> | |||
| <Button Grid.Row="3" Grid.Column="7" Name="SetBtm" Content="{Binding ConfirmBtnCont}" Command="{Binding ClickConfirmCommand}" Visibility="{Binding RouteBoxVis}"/> | |||
| <Button Grid.Row="4" Grid.Column="6" Grid.ColumnSpan="2" Name="ReadExsisted" Content="所选文件夹即为选手包" Command="{Binding ClickReadCommand}" Visibility="{Binding NewUserVis}"/> | |||
| <Button Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="2" Name="SwitchOSBtn" Content="{Binding SwitchOSBtnCont}" Command="{Binding ClickSwitchOSCommand}" Visibility="{Binding MenuVis}" /> | |||
| <Button Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="2" Name="UpdateBtn" Content="{Binding UpdateBtnCont}" Command="{Binding ClickUpdateCommand}" Visibility="{Binding MenuVis}" /> | |||
| <TextBlock Grid.Row="4" Grid.Column="2" Grid.ColumnSpan="2" FontSize="10" Text="{Binding UpdateInfo}" Visibility="{Binding UpdateInfoVis}" /> | |||
| @@ -35,6 +35,9 @@ using static System.Net.WebRequestMethods; | |||
| using File = System.IO.File; | |||
| using System.Linq; | |||
| using Installer; | |||
| using starter.viewmodel.settings; | |||
| using System.Security.Permissions; | |||
| using System.Windows.Media; | |||
| namespace starter.viewmodel.settings | |||
| { | |||
| @@ -63,6 +66,7 @@ namespace starter.viewmodel.settings | |||
| UploadReady = false; | |||
| LoginFailed = false; | |||
| launchLanguage = LaunchLanguage.cpp; | |||
| usingOS = ReadUsingOS(); | |||
| } | |||
| /// <summary> | |||
| @@ -113,7 +117,7 @@ namespace starter.viewmodel.settings | |||
| /// <returns></returns> | |||
| public Status checkUpdate() | |||
| { | |||
| UpdateInfo updateInfo = Tencent_cos_download.Check(); | |||
| UpdateInfo updateInfo = Tencent_cos_download.Check(usingOS); | |||
| if (updateInfo.newFileCount == -1) | |||
| { | |||
| if (updateInfo.changedFileCount == -1) | |||
| @@ -143,19 +147,19 @@ namespace starter.viewmodel.settings | |||
| public bool RememberUser() | |||
| { | |||
| int result = 0; | |||
| result |= Web.WriteUserEmail(Username); | |||
| result |= Web.WriteUserPassword(Password); | |||
| result |= Web.WriteJson("email", Username); | |||
| result |= Web.WriteJson("password", Password); | |||
| return result == 0; | |||
| } | |||
| public bool RecallUser() | |||
| { | |||
| Username = Web.ReadUserEmail(); | |||
| Username = Web.ReadJson("email"); | |||
| if (Username == null || Username.Equals("")) | |||
| { | |||
| Username = ""; | |||
| return false; | |||
| } | |||
| Password = Web.ReadUserPassword(); | |||
| Password = Web.ReadJson("password"); | |||
| if (Password == null || Username.Equals("")) | |||
| { | |||
| Password = ""; | |||
| @@ -166,14 +170,21 @@ namespace starter.viewmodel.settings | |||
| public bool ForgetUser() | |||
| { | |||
| int result = 0; | |||
| result |= Web.WriteUserEmail(""); | |||
| result |= Web.WriteUserPassword(""); | |||
| result |= Web.WriteJson("email", ""); | |||
| result |= Web.WriteJson("password", ""); | |||
| return result == 0; | |||
| } | |||
| public bool Update() | |||
| { | |||
| return Tencent_cos_download.Update(); | |||
| try | |||
| { | |||
| return Tencent_cos_download.Update(); | |||
| } | |||
| catch | |||
| { | |||
| return false; | |||
| } | |||
| } | |||
| public int Uninst() | |||
| { | |||
| @@ -214,6 +225,35 @@ namespace starter.viewmodel.settings | |||
| return -9; | |||
| return await web.UploadFiles(client, CodeRoute, Language, PlayerNum); | |||
| } | |||
| public bool WriteUsingOS() | |||
| { | |||
| string OS = ""; | |||
| switch (usingOS) | |||
| { | |||
| case UsingOS.Win: | |||
| OS = "win"; | |||
| break; | |||
| case UsingOS.Linux: | |||
| OS = "linux"; | |||
| break; | |||
| case UsingOS.OSX: | |||
| OS = "osx"; | |||
| break; | |||
| } | |||
| return Web.WriteJson("OS", OS) == 0; | |||
| } | |||
| public UsingOS ReadUsingOS() | |||
| { | |||
| string OS = Web.ReadJson("OS"); | |||
| if (OS == null) | |||
| return UsingOS.Win; | |||
| else if (OS.Equals("linux")) | |||
| return UsingOS.Linux; | |||
| else if (OS.Equals("osx")) | |||
| return UsingOS.OSX; | |||
| else | |||
| return UsingOS.Win; | |||
| } | |||
| /// <summary> | |||
| /// Route of files | |||
| /// </summary> | |||
| @@ -306,6 +346,11 @@ namespace starter.viewmodel.settings | |||
| { | |||
| get; set; | |||
| } | |||
| public enum UsingOS { Win, Linux, OSX }; | |||
| public UsingOS usingOS | |||
| { | |||
| get; set; | |||
| } | |||
| } | |||
| } | |||
| namespace Downloader | |||
| @@ -494,6 +539,10 @@ namespace Downloader | |||
| { | |||
| throw serverEx; | |||
| } | |||
| catch | |||
| { | |||
| MessageBox.Show($"下载{download_dir}时出现未知问题,请反馈"); | |||
| } | |||
| } | |||
| public static void GetNewHash() | |||
| @@ -533,7 +582,16 @@ namespace Downloader | |||
| } | |||
| } | |||
| public static UpdateInfo Check() | |||
| public static bool IsUserFile(string filename) | |||
| { | |||
| if (filename.Substring(filename.Length - 3, 3).Equals(".sh") || filename.Substring(filename.Length - 4, 4).Equals(".cmd")) | |||
| return true; | |||
| if (filename.Equals("AI.cpp") || filename.Equals("AI.py")) | |||
| return true; | |||
| return false; | |||
| } | |||
| public static UpdateInfo Check(SettingsModel.UsingOS OS) | |||
| { | |||
| string json, MD5, jsonName; | |||
| int newFile = 0, updateFile = 0; | |||
| @@ -577,27 +635,43 @@ namespace Downloader | |||
| json = r.ReadToEnd(); | |||
| json = json.Replace("\r", string.Empty).Replace("\n", string.Empty); | |||
| Dictionary<string, string> jsonDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json); | |||
| string updatingFolder = ""; | |||
| switch (OS) | |||
| { | |||
| case SettingsModel.UsingOS.Win: | |||
| updatingFolder = "THUAI6/win"; | |||
| break; | |||
| case SettingsModel.UsingOS.Linux: | |||
| updatingFolder = "THUAI6/lin"; | |||
| break; | |||
| case SettingsModel.UsingOS.OSX: | |||
| updatingFolder = "THUAI6/osx"; | |||
| break; | |||
| } | |||
| foreach (KeyValuePair<string, string> pair in jsonDict) | |||
| { | |||
| MD5 = GetFileMd5Hash(System.IO.Path.Combine(Data.FilePath, pair.Key)); | |||
| if (MD5.Length == 0) // 文档不存在 | |||
| newFileName.Add(pair.Key); | |||
| else if (MD5.Equals("conflict")) | |||
| if (pair.Key.Length > 10 && (pair.Key.Substring(0, 10).Equals(updatingFolder)) || pair.Key.Substring(pair.Key.Length - 4, 4).Equals(".pdf")) | |||
| { | |||
| if (pair.Key.Equals("THUAI6/win/CAPI/cpp/.vs/CAPI/v17/Browse.VC.db")) | |||
| MD5 = GetFileMd5Hash(System.IO.Path.Combine(Data.FilePath, pair.Key.TrimStart(new char[] { '.', '/' }))); | |||
| if (MD5.Length == 0) // 文档不存在 | |||
| newFileName.Add(pair.Key); | |||
| else if (MD5.Equals("conflict")) | |||
| { | |||
| MessageBox.Show($"visual studio未关闭:\n" + | |||
| $"对于visual studio 2022,可以更新,更新会覆盖visual studio中已经打开的选手包;\n" + | |||
| $"若使用其他版本的visual studio是继续更新出现问题,请汇报;\n" + | |||
| $"若您自行修改了选手包,请注意备份;\n" + | |||
| $"若关闭visual studio后仍弹出,请汇报。\n\n", | |||
| "visual studio未关闭", MessageBoxButton.OK, MessageBoxImage.Information); | |||
| if (pair.Key.Equals("THUAI6/win/CAPI/cpp/.vs/CAPI/v17/Browse.VC.db")) | |||
| { | |||
| MessageBox.Show($"visual studio未关闭:\n" + | |||
| $"对于visual studio 2022,可以更新,更新会覆盖visual studio中已经打开的选手包;\n" + | |||
| $"若使用其他版本的visual studio是继续更新出现问题,请汇报;\n" + | |||
| $"若您自行修改了选手包,请注意备份;\n" + | |||
| $"若关闭visual studio后仍弹出,请汇报。\n\n", | |||
| "visual studio未关闭", MessageBoxButton.OK, MessageBoxImage.Information); | |||
| } | |||
| else | |||
| MessageBox.Show($"检查{pair.Key}更新时遇到问题,请反馈", "读取出错", MessageBoxButton.OK, MessageBoxImage.Error); | |||
| } | |||
| else | |||
| MessageBox.Show($"检查{pair.Key}更新时遇到问题,请反馈", "读取出错", MessageBoxButton.OK, MessageBoxImage.Error); | |||
| else if (!MD5.Equals(pair.Value) && !IsUserFile(System.IO.Path.GetFileName(pair.Key))) // MD5不匹配 | |||
| updateFileName.Add(pair.Key); | |||
| } | |||
| else if (MD5 != pair.Value && System.IO.Path.GetFileName(pair.Key) != "AI.cpp" && System.IO.Path.GetFileName(pair.Key) != "AI.py") // MD5不匹配 | |||
| updateFileName.Add(pair.Key); | |||
| } | |||
| newFile = newFileName.Count; | |||
| @@ -648,8 +722,6 @@ namespace Downloader | |||
| Download(); | |||
| if (updateFailed.Count == 0) | |||
| return true; | |||
| else | |||
| Check(); | |||
| } | |||
| return false; | |||
| } | |||
| @@ -667,7 +739,7 @@ namespace Downloader | |||
| foreach (string filename in newFileName) | |||
| { | |||
| //Console.WriteLine(newFile + 1 + "/" + totalnew + ":开始下载" + filename); | |||
| Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename); | |||
| Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename.TrimStart(new char[] { '.', '/' })); | |||
| //Console.WriteLine(filename + "下载完毕!" + Environment.NewLine); | |||
| newFile++; | |||
| } | |||
| @@ -677,12 +749,23 @@ namespace Downloader | |||
| try | |||
| { | |||
| File.Delete(System.IO.Path.Combine(@Data.FilePath, filename)); | |||
| Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename); | |||
| Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename.TrimStart(new char[] { '.', '/' })); | |||
| } | |||
| catch (System.IO.IOException) | |||
| { | |||
| updateFailed = updateFailed.Append(filename).ToList(); | |||
| } | |||
| catch | |||
| { | |||
| if (filename.Substring(filename.Length - 4, 4).Equals(".pdf")) | |||
| { | |||
| MessageBox.Show($"由于曾经发生过的访问冲突,下载器无法更新{filename}\n" | |||
| + $"请手动删除{filename},然后再试一次。"); | |||
| } | |||
| else | |||
| MessageBox.Show($"更新{filename}时遇到未知问题,请反馈"); | |||
| updateFailed = updateFailed.Append(filename).ToList(); | |||
| } | |||
| //Console.WriteLine(filename + "下载完毕!" + Environment.NewLine); | |||
| updateFile++; | |||
| } | |||
| @@ -692,19 +775,20 @@ namespace Downloader | |||
| catch (CosClientException clientEx) | |||
| { | |||
| // 请求失败 | |||
| MessageBox.Show("网络错误"); | |||
| MessageBox.Show("连接错误:" + clientEx.ToString()); | |||
| Console.WriteLine("CosClientException: " + clientEx.ToString() + Environment.NewLine); | |||
| return; | |||
| } | |||
| catch (CosServerException serverEx) | |||
| { | |||
| // 请求失败 | |||
| MessageBox.Show("网络错误"); | |||
| MessageBox.Show("连接错误:" + serverEx.ToString()); | |||
| Console.WriteLine("CosClientException: " + serverEx.ToString() + Environment.NewLine); | |||
| return; | |||
| } | |||
| catch (Exception) | |||
| { | |||
| MessageBox.Show("未知错误且无法定位到出错文件,请反馈"); | |||
| throw; | |||
| } | |||
| } | |||
| @@ -840,7 +924,7 @@ namespace Downloader | |||
| using StreamWriter sw = new StreamWriter(fs2); | |||
| fs2.SetLength(0); | |||
| sw.Write(JsonConvert.SerializeObject(dict)); | |||
| Check(); | |||
| Check(SettingsModel.UsingOS.Win); | |||
| Download(); | |||
| if (File.Exists(Data.FilePath + "/THUAI6/AI.cpp")) | |||
| { | |||
| @@ -1126,7 +1210,7 @@ namespace Downloader | |||
| { | |||
| if (Data.FilePath != null && Directory.Exists(Data.FilePath)) | |||
| { | |||
| Check(); | |||
| Check(SettingsModel.UsingOS.Win); | |||
| break; | |||
| } | |||
| else | |||
| @@ -1201,7 +1285,7 @@ namespace Downloader | |||
| string keyHead = "Installer/"; | |||
| Tencent_cos_download downloader = new Tencent_cos_download(); | |||
| string hashName = "installerHash.json"; | |||
| string dir = Directory.GetCurrentDirectory(); | |||
| string dir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName); | |||
| int result = 0; | |||
| try | |||
| { | |||
| @@ -1243,7 +1327,7 @@ namespace Downloader | |||
| else | |||
| { | |||
| result = 1; | |||
| awaitUpdate.Append(pair.Key); | |||
| awaitUpdate = awaitUpdate.Append(pair.Key).ToList(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1255,6 +1339,37 @@ namespace Downloader | |||
| File.WriteAllText(@System.IO.Path.Combine(dir, "updateList.json"), Contentjson); | |||
| return result; | |||
| } | |||
| static public bool SelfUpdateDismissed() | |||
| { | |||
| string json; | |||
| string dir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName); | |||
| if (!File.Exists(System.IO.Path.Combine(dir, "updateList.json"))) | |||
| return false; | |||
| 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; | |||
| if (json != null) | |||
| jsonList = JsonConvert.DeserializeObject<List<string>>(json); | |||
| else | |||
| return false; | |||
| if (jsonList != null && jsonList.Contains("Dismiss")) | |||
| { | |||
| listJsonClear(System.IO.Path.Combine(dir, "updateList.json")); | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| static private void listJsonClear(string directory) | |||
| { | |||
| List<string> list = new List<string>(); | |||
| list.Add("None"); | |||
| StreamWriter sw = new StreamWriter(directory, false); | |||
| sw.WriteLine(JsonConvert.SerializeObject(list)); | |||
| sw.Close(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1499,7 +1614,7 @@ namespace WebConnect | |||
| } | |||
| } | |||
| public static int WriteUserEmail(string email) | |||
| public static int WriteJson(string key, string data) | |||
| { | |||
| try | |||
| { | |||
| @@ -1513,13 +1628,13 @@ namespace WebConnect | |||
| } | |||
| Dictionary<string, string> dict = new Dictionary<string, string>(); | |||
| dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json); | |||
| if (!dict.ContainsKey("email")) | |||
| if (!dict.ContainsKey(key)) | |||
| { | |||
| dict.Add("email", email); | |||
| dict.Add(key, data); | |||
| } | |||
| else | |||
| { | |||
| dict["email"] = email; | |||
| dict[key] = data; | |||
| } | |||
| sr.Close(); | |||
| fs.Close(); | |||
| @@ -1536,44 +1651,7 @@ namespace WebConnect | |||
| } | |||
| } | |||
| public static int WriteUserPassword(string password) | |||
| { | |||
| try | |||
| { | |||
| string savepath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json"); | |||
| FileStream fs = new FileStream(savepath, FileMode.Open, FileAccess.ReadWrite); | |||
| StreamReader sr = new StreamReader(fs); | |||
| string json = sr.ReadToEnd(); | |||
| if (json == null || json == "") | |||
| { | |||
| json += @"{""THUAI6""" + ":" + @"""2023""}"; | |||
| } | |||
| Dictionary<string, string> dict = new Dictionary<string, string>(); | |||
| dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json); | |||
| if (!dict.ContainsKey("password")) | |||
| { | |||
| dict.Add("password", password); | |||
| } | |||
| else | |||
| { | |||
| dict["password"] = password; | |||
| } | |||
| sr.Close(); | |||
| fs.Close(); | |||
| FileStream fs2 = new FileStream(savepath, FileMode.Open, FileAccess.ReadWrite); | |||
| StreamWriter sw = new StreamWriter(fs2); | |||
| sw.WriteLine(JsonConvert.SerializeObject(dict)); | |||
| sw.Close(); | |||
| fs2.Close(); | |||
| return 0;//成功 | |||
| } | |||
| catch | |||
| { | |||
| return -1;//失败,THUAI6.json 文件不存在或者已被占用 | |||
| } | |||
| } | |||
| public static string ReadUserPassword() | |||
| public static string ReadJson(string key) | |||
| { | |||
| try | |||
| { | |||
| @@ -1587,7 +1665,9 @@ namespace WebConnect | |||
| json += @"{""THUAI6""" + ":" + @"""2023""}"; | |||
| } | |||
| dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json); | |||
| return dict["password"]; | |||
| fs.Close(); | |||
| sr.Close(); | |||
| return dict[key]; | |||
| } | |||
| catch | |||
| @@ -1596,27 +1676,6 @@ namespace WebConnect | |||
| } | |||
| } | |||
| public static string ReadUserEmail() | |||
| { | |||
| try | |||
| { | |||
| string savepath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json"); | |||
| FileStream fs = new FileStream(savepath, FileMode.Open, FileAccess.Read); | |||
| StreamReader sr = new StreamReader(fs); | |||
| string json = sr.ReadToEnd(); | |||
| Dictionary<string, string> dict = new Dictionary<string, string>(); | |||
| if (json == null || json == "") | |||
| { | |||
| json += @"{""THUAI6""" + ":" + @"""2023""}"; | |||
| } | |||
| dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json); | |||
| return dict["email"]; | |||
| } | |||
| catch | |||
| { | |||
| return null; | |||
| } | |||
| } | |||
| public bool ReadToken() // 读取token | |||
| { | |||
| try | |||
| @@ -33,22 +33,23 @@ namespace starter.viewmodel.settings | |||
| public SettingsViewModel() | |||
| { | |||
| Program.Tencent_cos_download.UpdateHash(); | |||
| //Program.Tencent_cos_download.UpdateHash(); | |||
| Status = SettingsModel.Status.working; | |||
| switch (Program.Tencent_cos_download.CheckSelfVersion()) | |||
| string CurrentDirectory = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName); | |||
| //MessageBox.Show("更新器工作正常"); | |||
| if (!Program.Tencent_cos_download.SelfUpdateDismissed()) | |||
| { | |||
| case 1: | |||
| if (MessageBoxResult.Yes == MessageBox.Show("下载器需要更新,是否现在更新", "需要更新", MessageBoxButton.YesNo)) | |||
| { | |||
| Process.Start(Path.Combine(Directory.GetCurrentDirectory(), "InstallerUpdater.exe")); | |||
| switch (Program.Tencent_cos_download.CheckSelfVersion()) | |||
| { | |||
| case 1: | |||
| Process.Start(System.IO.Path.Combine(CurrentDirectory, "InstallerUpdater.exe")); | |||
| Environment.Exit(0); | |||
| } | |||
| break; | |||
| case -1: | |||
| MessageBox.Show("下载器更新检查出错,将继续启动现有下载器"); | |||
| break; | |||
| break; | |||
| case -1: | |||
| MessageBox.Show("下载器更新检查出错,将继续启动现有下载器"); | |||
| break; | |||
| } | |||
| } | |||
| //实例化BackgroundWorker | |||
| @@ -78,6 +79,7 @@ namespace starter.viewmodel.settings | |||
| else | |||
| RememberMe = false; | |||
| this.RaisePropertyChanged("RememberMe"); | |||
| this.RaisePropertyChanged("SwitchOSBtnCont"); | |||
| //在启动时立刻检查更新,确保选手启动最新版选手包 | |||
| //若有更新,将启动键改为更新键; | |||
| //相应地,使用login界面启动; | |||
| @@ -139,6 +141,7 @@ namespace starter.viewmodel.settings | |||
| } | |||
| MessageBox.Show($"以下文件因被占用而未能成功更新:\n{updateFailList}请关闭它们,并再试一次"); | |||
| Program.ResetUpdateFailedInfo(); | |||
| obj.checkUpdate(); | |||
| Status = SettingsModel.Status.successful; | |||
| this.RaisePropertyChanged("UpdateBtnCont"); | |||
| this.RaisePropertyChanged("UpdateInfo"); | |||
| @@ -303,6 +306,23 @@ namespace starter.viewmodel.settings | |||
| return ans; | |||
| } | |||
| } | |||
| public string SwitchOSBtnCont | |||
| { | |||
| get | |||
| { | |||
| switch (obj.usingOS) | |||
| { | |||
| case SettingsModel.UsingOS.Win: | |||
| return "当前系统:Windows"; | |||
| case SettingsModel.UsingOS.Linux: | |||
| return "当前系统:Linux"; | |||
| case SettingsModel.UsingOS.OSX: | |||
| return "当前系统:macOS"; | |||
| default: | |||
| return "当前系统:无效的名称"; | |||
| } | |||
| } | |||
| } | |||
| public int PlayerNum | |||
| { | |||
| get | |||
| @@ -1030,6 +1050,40 @@ namespace starter.viewmodel.settings | |||
| return clickReadCommand; | |||
| } | |||
| } | |||
| private BaseCommand clickSwitchOSCommand; | |||
| public BaseCommand ClickSwitchOSCommand | |||
| { | |||
| get | |||
| { | |||
| if (clickSwitchOSCommand == null) | |||
| { | |||
| clickSwitchOSCommand = new BaseCommand(new Action<object>(o => | |||
| { | |||
| switch (obj.usingOS) | |||
| { | |||
| case SettingsModel.UsingOS.Win: | |||
| obj.usingOS = SettingsModel.UsingOS.Linux; | |||
| break; | |||
| case SettingsModel.UsingOS.Linux: | |||
| obj.usingOS = SettingsModel.UsingOS.OSX; | |||
| break; | |||
| case SettingsModel.UsingOS.OSX: | |||
| obj.usingOS = SettingsModel.UsingOS.Win; | |||
| break; | |||
| } | |||
| this.RaisePropertyChanged("SwitchOSBtnCont"); | |||
| obj.WriteUsingOS(); | |||
| obj.checkUpdate(); | |||
| UpdateInfoVis = Visibility.Visible; | |||
| this.RaisePropertyChanged("UpdateBtnCont"); | |||
| this.RaisePropertyChanged("UpdateInfo"); | |||
| this.RaisePropertyChanged("UpdateInfoVis"); | |||
| })); | |||
| } | |||
| return clickSwitchOSCommand; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -28,17 +28,27 @@ namespace InstallerUpdater | |||
| public MainWindow() | |||
| { | |||
| InitializeComponent(); | |||
| MessageBox.Show("这是旧版"); | |||
| //MessageBox.Show("这是旧版"); | |||
| //MessageBox.Show("下载器更新功能正常"); | |||
| asyncDownloader.DoWork += AsyncDownloader_DoWork; | |||
| asyncDownloader.RunWorkerCompleted += AsyncDownloader_RunWorkerCompleted; | |||
| if (asyncDownloader.IsBusy) | |||
| if (MessageBoxResult.Yes == MessageBox.Show("发现下载器更新,是否更新下载器?", "下载器更新", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes)) | |||
| { | |||
| MessageBox.Show("更新失败,请汇报"); | |||
| if (asyncDownloader.IsBusy) | |||
| { | |||
| MessageBox.Show("更新器已在运行"); | |||
| Process.Start(System.IO.Path.Combine(Updater.Dir, "Installer.exe")); | |||
| Application.Current.Shutdown(); | |||
| } | |||
| else | |||
| asyncDownloader.RunWorkerAsync(); | |||
| } | |||
| else | |||
| { | |||
| Updater.TellDismiss(); | |||
| Process.Start(System.IO.Path.Combine(Updater.Dir, "Installer.exe")); | |||
| Application.Current.Shutdown(); | |||
| } | |||
| else | |||
| asyncDownloader.RunWorkerAsync(); | |||
| } | |||
| private void AsyncDownloader_RunWorkerCompleted(object? sender, RunWorkerCompletedEventArgs e) | |||
| @@ -11,12 +11,14 @@ using System.Windows.Markup; | |||
| using System; | |||
| using System.Security.Cryptography; | |||
| using System.Diagnostics; | |||
| using System.Windows; | |||
| using System.Windows.Documents; | |||
| namespace Program | |||
| { | |||
| class Updater | |||
| { | |||
| public static string Dir = Directory.GetCurrentDirectory(); | |||
| public static string Dir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName); | |||
| public static string InstallerName = "Installer.exe"; | |||
| public static string jsonKey = "installerHash.json"; | |||
| public static string KeyHead = "Installer/"; | |||
| @@ -32,17 +34,59 @@ namespace Program | |||
| 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); | |||
| if (!todo.Equals("None")) | |||
| { | |||
| File.Delete(Path.Combine(Dir, todo)); | |||
| download(Path.Combine(Dir, todo), KeyHead + todo); | |||
| } | |||
| } | |||
| } | |||
| catch (IOException) | |||
| { | |||
| MessageBox.Show("下载器本体未能成功关闭"); | |||
| return false; | |||
| } | |||
| catch | |||
| { | |||
| MessageBox.Show("尝试下载时出现问题"); | |||
| return false; | |||
| } | |||
| return true; | |||
| } | |||
| public static int TellDismiss() | |||
| { | |||
| try | |||
| { | |||
| string savepath = System.IO.Path.Combine(Dir, "updateList.json"); | |||
| FileStream fs = new FileStream(savepath, FileMode.Open, FileAccess.ReadWrite); | |||
| StreamReader sr = new StreamReader(fs); | |||
| string json = sr.ReadToEnd(); | |||
| if (json == null || json == "") | |||
| { | |||
| json += @"{""None""}"; | |||
| } | |||
| List<string> ls = new List<string>(); | |||
| ls = JsonConvert.DeserializeObject<List<string>>(json); | |||
| if (!ls.Contains("Dismiss")) | |||
| { | |||
| ls.Add("Dismiss"); | |||
| } | |||
| sr.Close(); | |||
| fs.Close(); | |||
| StreamWriter sw = new StreamWriter(System.IO.Path.Combine(Dir, "updateList.json"), false); | |||
| sw.WriteLine(JsonConvert.SerializeObject(ls)); | |||
| sw.Close(); | |||
| return 0;//成功 | |||
| } | |||
| catch | |||
| { | |||
| return -1;//失败 | |||
| } | |||
| } | |||
| public static void download(string download_dir, string key) | |||
| { | |||
| // download_dir标记根文件夹路径,key为相对根文件夹的路径(不带./) | |||
| @@ -8,6 +8,7 @@ public class MapManager : MonoBehaviour | |||
| // Start is called before the first frame update | |||
| private bool mapFinished; | |||
| private MessageOfMap map; | |||
| private MessageOfStudent Student; | |||
| private int rowCount = 50; | |||
| private int colCount = 50; | |||
| @@ -16,6 +17,15 @@ public class MapManager : MonoBehaviour | |||
| public GameObject land; | |||
| public GameObject door; | |||
| public GameObject window; | |||
| public GameObject box; | |||
| public GameObject book; | |||
| public GameObject student_1; | |||
| public GameObject student_2; | |||
| public GameObject student_3; | |||
| public GameObject student_4; | |||
| public GameObject Monster_1; | |||
| public GameObject Monster_2; | |||
| public GameObject Monster_3; | |||
| void Start() | |||
| { | |||
| mapFinished = false; | |||
| @@ -27,16 +37,16 @@ public class MapManager : MonoBehaviour | |||
| if (!mapFinished && MessageReceiver.map != null) | |||
| { | |||
| map = MessageReceiver.map; | |||
| Debug.Log("valid map"); | |||
| //Debug.Log("valid map"); | |||
| mapFinished = true; | |||
| ShowMap(map); | |||
| } | |||
| } | |||
| private void ShowMap(MessageOfMap map) | |||
| { | |||
| var position = new Vector3(-24.5f, 12.25f, 12.25f); | |||
| var position = new Vector3(-0.5f, 49.5f, 49.5f); | |||
| var block = new GameObject(); | |||
| for (int i = 0; i < rowCount; i++) | |||
| { | |||
| @@ -49,10 +59,9 @@ public class MapManager : MonoBehaviour | |||
| Instantiate(block, position, new Quaternion(0, 0, 0, 0)); | |||
| } | |||
| } | |||
| position.x = -24.5f; | |||
| position.z=position.y = position.y - 0.5f; | |||
| position.x = -0.5f; | |||
| position.z=position.y = position.y - 1.0f; | |||
| } | |||
| } | |||
| private GameObject ShowBlock(PlaceType obj) | |||
| @@ -66,7 +75,9 @@ public class MapManager : MonoBehaviour | |||
| case PlaceType.Door5: return door; | |||
| case PlaceType.Door6: return door; | |||
| case PlaceType.Window: return window; | |||
| default:return null; | |||
| case PlaceType.Chest:return box; | |||
| case PlaceType.Classroom:return book; | |||
| default:return land; | |||
| } | |||
| } | |||
| } | |||
| @@ -9,7 +9,7 @@ using System.Data; | |||
| public class MessageReceiver : MonoBehaviour | |||
| { | |||
| private bool isMap; | |||
| private static int studentNum = 2; | |||
| // Start is called before the first frame update | |||
| async void Start() | |||
| { | |||
| @@ -17,18 +17,50 @@ public class MessageReceiver : MonoBehaviour | |||
| var client = new AvailableService.AvailableServiceClient(channel); | |||
| PlayerMsg msg = new PlayerMsg(); | |||
| msg.PlayerType = PlayerType.StudentPlayer; | |||
| msg.PlayerId = 0; | |||
| isMap = true; | |||
| msg.PlayerId = 3000; | |||
| map = null; | |||
| var response = client.AddPlayer(msg); | |||
| while (await response.ResponseStream.MoveNext()) | |||
| //while (await response.ResponseStream.MoveNext()) | |||
| //{ | |||
| // var responseVal = response.ResponseStream.Current; | |||
| // if (isMap) | |||
| // { | |||
| // map = responseVal.ObjMessage[0].MapMessage; | |||
| // //Debug.Log(map.ToString()); | |||
| // isMap = false; | |||
| // for (int i = 0; i < studentNum; i++) | |||
| // Instantiate(student_1, new Vector3(0f, 0f, 10.0f), new Quaternion(0, 0, 0, 0)); | |||
| // } | |||
| // else | |||
| // { | |||
| // for (int i = 0; i < studentNum; i++) | |||
| // { | |||
| // Student[i] = responseVal.ObjMessage[i].StudentMessage; | |||
| // } | |||
| // } | |||
| //} | |||
| if(await response.ResponseStream.MoveNext()) | |||
| { | |||
| var responseVal = response.ResponseStream.Current; | |||
| map = responseVal.ObjMessage[0].MapMessage; | |||
| } | |||
| if (await response.ResponseStream.MoveNext()) | |||
| { | |||
| var responseVal = response.ResponseStream.Current; | |||
| if (isMap) | |||
| for (int i = 0; i < studentNum; i++) | |||
| { | |||
| map = responseVal.ObjMessage[0].MapMessage; | |||
| //Debug.Log(map.ToString()); | |||
| isMap = false; | |||
| Student[i] = responseVal.ObjMessage[i].StudentMessage; | |||
| Instantiate(student_1, new Vector3(0f, 0f, 10.0f), new Quaternion(0, 0, 0, 0)); | |||
| } | |||
| } | |||
| while(await response.ResponseStream.MoveNext()) | |||
| { | |||
| var responseVal = response.ResponseStream.Current; | |||
| for(int i=0;i<studentNum;i++) | |||
| { | |||
| Student[i] = responseVal.ObjMessage[i].StudentMessage; | |||
| } | |||
| } | |||
| } | |||
| @@ -36,6 +68,7 @@ public class MessageReceiver : MonoBehaviour | |||
| void Update() | |||
| { | |||
| } | |||
| public static MessageOfMap map; | |||
| public static MessageOfStudent[] Student = new MessageOfStudent[studentNum]; | |||
| public GameObject student_1; | |||
| } | |||
| @@ -0,0 +1,46 @@ | |||
| using System.Collections; | |||
| using System.Collections.Generic; | |||
| using UnityEngine; | |||
| using Grpc.Core; | |||
| using Google.Protobuf; | |||
| using Protobuf; | |||
| using System.Data; | |||
| public class Student : MonoBehaviour | |||
| { | |||
| // Start is called before the first frame update | |||
| void Start() | |||
| { | |||
| num = studentCount; | |||
| studentCount++; | |||
| anim = GetComponent<Animator>(); | |||
| occupation = MessageReceiver.Student[num].StudentType; | |||
| transform.position = lastPosition = new Vector3(MessageReceiver.Student[num].Y / 1000.0f, | |||
| 50.0f - MessageReceiver.Student[num].X / 1000.0f, | |||
| 50.0f - MessageReceiver.Student[num].X / 1000.0f - 0.5f); | |||
| } | |||
| // Update is called once per frame | |||
| void Update() | |||
| { | |||
| var currentPosition = new Vector3(MessageReceiver.Student[num].Y / 1000.0f, | |||
| 50.0f - MessageReceiver.Student[num].X / 1000.0f, | |||
| 50.0f - MessageReceiver.Student[num].X / 1000.0f - 0.5f); | |||
| Vector3 step = currentPosition - lastPosition; | |||
| if (step != Vector3.zero) | |||
| { | |||
| transform.position = currentPosition; | |||
| anim.SetBool("isRun", true); | |||
| } | |||
| else | |||
| { | |||
| anim.SetBool("isRun", false); | |||
| } | |||
| lastPosition = currentPosition; | |||
| } | |||
| private int num; | |||
| private StudentType occupation; | |||
| private Vector3 lastPosition = new Vector3(0, 0, 10.0f); | |||
| private static int studentCount = 0; | |||
| private Animator anim; | |||
| } | |||