diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7c978b31..7da21415 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,12 +1,8 @@ name: deploy on: push: - branches: [dev, main, master] - pull_request: - branches: [dev, main, master] + branches: [main, master] -env: - version: 1.1.0.0 jobs: deploy-to-tencent-cos: @@ -29,8 +25,6 @@ jobs: mkdir D:\a\publish - name: Copy THUAI7 run: Copy-Item -recurse D:\a\THUAI7\THUAI7\ D:\a\mirror\ - - name: Test - run: tree D:\a\mirror - name: Remove directories not needed run: | Remove-Item -recurse -force D:\a\mirror\.git @@ -45,15 +39,8 @@ jobs: - name: Build Client run: dotnet publish "./logic/Client/Client.csproj" -o "D:\a\mirror\logic\Client" -f net8.0-windows10.0.19041.0 -c Release -p:RuntimeIdentifierOverride=win10-x64 -p:WindowsPackageType=None -p:WindowsAppSDKSelfContained=true - name: Deploy to bucket - run: dotnet run --project "./dependency/deploy/deploy.csproj" ${{ secrets.INSTALLER_COS_SECRET_ID }} ${{ secrets.INSTALLER_COS_SECRET_KEY }} + run: dotnet run --project "./dependency/deploy/deploy.csproj" ${{ secrets.INSTALLER_COS_SECRET_ID }} ${{ secrets.INSTALLER_COS_SECRET_KEY }} "check" - name: Get installer package(No Key contained for safety) run: | - $version=Get-ChildItem -Path D:\a\publish | ForEach-Object { $_.name } - [Environment]::SetEnvironmentVariable("version", $version, "Machine") - dotnet publish "./installer/installer.csproj" -o "D:\a\installer" -f net8.0-windows10.0.19041.0 -c Release -p:RuntimeIdentifierOverride=win10-x64 -p:WindowsPackageType=None -p:WindowsAppSDKSelfContained=true - ./dependency/7z/7za.exe a -r D:\a\publish\Installer_v${version}.zip D:\a\installer\* - - name: Upload installer package - uses: actions/upload-artifact@v4 - with: - name: Installer_v${{ env.version }}.zip - path: D:\a\publish\Installer_v${{ env.version }}.zip + dotnet publish "./installer/installer.csproj" -o "D:\a\publish" -f net8.0-windows10.0.19041.0 -c Release -p:RuntimeIdentifierOverride=win10-x64 -p:WindowsPackageType=None -p:WindowsAppSDKSelfContained=true + dotnet run --project "./dependency/deploy/deploy.csproj" ${{ secrets.INSTALLER_COS_SECRET_ID }} ${{ secrets.INSTALLER_COS_SECRET_KEY }} "upload" \ No newline at end of file diff --git a/dependency/deploy/Program.cs b/dependency/deploy/Program.cs index 7531360e..56392ca0 100644 --- a/dependency/deploy/Program.cs +++ b/dependency/deploy/Program.cs @@ -3,6 +3,7 @@ using installer.Services; using System.Collections.Concurrent; using System.Diagnostics; +using System.IO.Compression; Logger Log = LoggerProvider.FromConsole(); @@ -17,56 +18,74 @@ d.Log.Partner.Add(Log); // 每次更新需要更新默认值 d.CurrentVersion = new TVersion(); -File.Create(Path.Combine("D:\\a\\publish", d.CurrentVersion.InstallerVersion.ToString())); -if (d.CheckUpdate()) +switch (args[2]) { - foreach (var r in d.Data.MD5Update) - { - Log.LogInfo($"{r.state}, {r.name}"); - } + case "check": - d.Data.SaveMD5Data(); - List l = new List(); - foreach (var r in d.Data.MD5Update) - { - var n = r.name.Replace('\\', '/'); - n = n.TrimStart('.').TrimStart('/'); - if (r.state == System.Data.DataRowState.Added || r.state == System.Data.DataRowState.Modified) + if (d.CheckUpdate()) { - l.Add(Cloud.UploadFileAsync(Path.Combine(d.Data.Config.InstallPath, r.name), n)); + foreach (var r in d.Data.MD5Update) + { + Log.LogInfo($"{r.state}, {r.name}"); + } + + d.Data.SaveMD5Data(); + List l = new List(); + foreach (var r in d.Data.MD5Update) + { + var n = r.name.Replace('\\', '/'); + n = n.TrimStart('.').TrimStart('/'); + if (r.state == System.Data.DataRowState.Added || r.state == System.Data.DataRowState.Modified) + { + l.Add(Cloud.UploadFileAsync(Path.Combine(d.Data.Config.InstallPath, r.name), n)); + } + else if (r.state == System.Data.DataRowState.Deleted) + { + l.Add(Cloud.DeleteFileAsync(n)); + } + } + Task.WaitAll(l.ToArray()); } - else if (r.state == System.Data.DataRowState.Deleted) + else { - l.Add(Cloud.DeleteFileAsync(n)); + Log.LogInfo("Nothing to update"); } - } - Task.WaitAll(l.ToArray()); -} -else -{ - Log.LogInfo("Nothing to update"); -} -d.Data.SaveMD5Data(); -Cloud.UploadFile(d.Data.MD5DataPath, "hash.json"); + d.Data.SaveMD5Data(); + Cloud.UploadFile(d.Data.MD5DataPath, "hash.json"); -Cloud.UploadFile(Path.Combine(d.Data.Config.InstallPath, "CAPI", "cpp", "API", "src", "AI.cpp"), - $"Templates/t.{d.CurrentVersion.TemplateVersion}.cpp"); -Cloud.UploadFile(Path.Combine(d.Data.Config.InstallPath, "CAPI", "python", "PyAPI", "AI.py"), - $"Templates/t.{d.CurrentVersion.TemplateVersion}.py"); -Log.LogInfo("User code uploaded."); + Cloud.UploadFile(Path.Combine(d.Data.Config.InstallPath, "CAPI", "cpp", "API", "src", "AI.cpp"), + $"Templates/t.{d.CurrentVersion.TemplateVersion}.cpp"); + Cloud.UploadFile(Path.Combine(d.Data.Config.InstallPath, "CAPI", "python", "PyAPI", "AI.py"), + $"Templates/t.{d.CurrentVersion.TemplateVersion}.py"); + Log.LogInfo("User code uploaded."); -var list = (from i in d.Data.MD5Data - select i.Key.Replace(Path.DirectorySeparatorChar, '/').TrimStart('.').TrimStart('/')).ToArray(); -Log.LogInfo(list[0]); -using (FileStream s = new FileStream(Path.Combine(d.Data.Config.InstallPath, "compress.csv"), FileMode.Create, FileAccess.Write)) -using (StreamWriter w = new StreamWriter(s)) -{ - foreach (var item in list) - { - w.WriteLine("https://thuai7-1319625962.cos.ap-beijing.myqcloud.com/" + item); - } -} -Cloud.UploadFile(Path.Combine(d.Data.Config.InstallPath, "compress.csv"), "compress.csv"); -Log.LogInfo("Compress csv generated."); + var list = (from i in d.Data.MD5Data + select i.Key.Replace(Path.DirectorySeparatorChar, '/').TrimStart('.').TrimStart('/')).ToArray(); + Log.LogInfo(list[0]); + using (FileStream s = new FileStream(Path.Combine(d.Data.Config.InstallPath, "compress.csv"), FileMode.Create, FileAccess.Write)) + using (StreamWriter w = new StreamWriter(s)) + { + foreach (var item in list) + { + w.WriteLine("https://thuai7-1319625962.cos.ap-beijing.myqcloud.com/" + item); + } + } + Cloud.UploadFile(Path.Combine(d.Data.Config.InstallPath, "compress.csv"), "compress.csv"); + Log.LogInfo("Compress csv generated."); + break; + case "upload": + d.UpdateMD5(); + if (d.Data.FileHashData.TVersion.InstallerVersion < d.CurrentVersion.InstallerVersion) + { + Cloud.DownloadFile(@"D:\a\publish\Secret.csv", "Secret.csv"); + ZipFile.CreateFromDirectory(@"D:\a\publish", @$"D:\a\Installer_v{d.CurrentVersion.InstallerVersion}.zip", CompressionLevel.SmallestSize, false); + Cloud.UploadFile(@$"D:\a\Installer_v{d.CurrentVersion.InstallerVersion}.zip", $"Setup/Installer_v{d.CurrentVersion.InstallerVersion}.zip"); + } + else + { + Log.LogInfo("No installer version update found."); + } + break; +} \ No newline at end of file diff --git a/installer/Data/MD5FileData.cs b/installer/Data/MD5FileData.cs index 65a63cda..39fa7fa6 100644 --- a/installer/Data/MD5FileData.cs +++ b/installer/Data/MD5FileData.cs @@ -32,7 +32,7 @@ public class TVersion public Version TemplateVersion = new Version(1, 0, 0, 3); // 本体版本 [JsonInclude] - public Version InstallerVersion = new Version(1, 1, 0, 0); + public Version InstallerVersion = new Version(1, 1, 0, 2); public static bool operator <(TVersion l, TVersion r) { return l.LibVersion < r.LibVersion || l.TemplateVersion < r.TemplateVersion || l.InstallerVersion < r.InstallerVersion; diff --git a/installer/ViewModel/DebugViewModel.cs b/installer/ViewModel/DebugViewModel.cs index 24d9ac0b..fe04591b 100644 --- a/installer/ViewModel/DebugViewModel.cs +++ b/installer/ViewModel/DebugViewModel.cs @@ -273,12 +273,14 @@ private void ServerExited(object? sender, EventArgs e) protected Process? server; public event EventHandler? OnServerLaunched; public event EventHandler? OnServerExited; + public bool LaunchServer() { server = Process.Start(new ProcessStartInfo() { FileName = Downloader.Data.Config.DevServerPath ?? Path.Combine(Downloader.Data.Config.InstallPath, "logic", "Server", "Server.exe"), Arguments = $"--ip 0.0.0.0 --port {Port} --teamCount {TeamCount} --shipNum {ShipCount}", + WorkingDirectory = Downloader.Data.Config.InstallPath }); if (server is null) { @@ -296,7 +298,6 @@ public bool LaunchServer() return true; } - public bool LaunchClient(int team, int player, int ship) { Downloader.Data.Config.Commands.TeamID = team; @@ -313,6 +314,7 @@ public bool LaunchClient(int team, int player, int ship) var client = Process.Start(new ProcessStartInfo() { FileName = Downloader.Data.Config.DevClientPath ?? Path.Combine(Downloader.Data.Config.InstallPath, "logic", "Client", "Client.exe"), + WorkingDirectory = Downloader.Data.Config.InstallPath }); if (client is null) { @@ -341,7 +343,8 @@ public bool LaunchCppAPI(int team, int player) var cpp = Process.Start(new ProcessStartInfo() { FileName = Downloader.Data.Config.DevCppPath ?? exe, - Arguments = $"-I {IP} -P {Port} -t {team} -p {player} -o" + Arguments = $"-I {IP} -P {Port} -t {team} -p {player} -o -d", + WorkingDirectory = Downloader.Data.Config.InstallPath }); if (cpp is null) { @@ -379,7 +382,8 @@ public bool LaunchPyAPI(int team, int player) FileName = "cmd.exe", Arguments = "/c python " + (Downloader.Data.Config.DevPyPath ?? Path.Combine(Downloader.Data.Config.InstallPath, "CAPI", "python", "PyAPI", "main.py")) - + $" -I {IP} -P {Port} -t {team} -p {player} -o" + + $" -I {IP} -P {Port} -t {team} -p {player} -o -d", + WorkingDirectory = Downloader.Data.Config.InstallPath }); if (py is null) { diff --git a/interface/interface_playback/Assets/Plugins.meta b/interface/interface_playback/Assets/Plugins.meta new file mode 100644 index 00000000..4032dbbc --- /dev/null +++ b/interface/interface_playback/Assets/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 550f42af462710b459b66720b19cca16 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/interface/interface_playback/Assets/Scripts/Playback.meta b/interface/interface_playback/Assets/Scripts/Playback.meta new file mode 100644 index 00000000..97f295d7 --- /dev/null +++ b/interface/interface_playback/Assets/Scripts/Playback.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0a847955f4659d24e9a62b4dbb44b481 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/interface/interface_playback/Assets/Scripts/Playback/MessageReader.cs b/interface/interface_playback/Assets/Scripts/Playback/MessageReader.cs new file mode 100644 index 00000000..062d0c8d --- /dev/null +++ b/interface/interface_playback/Assets/Scripts/Playback/MessageReader.cs @@ -0,0 +1,134 @@ + +using Google.Protobuf; +using Protobuf; +using System; +using System.IO; +using System.IO.Compression; + +namespace Playback +{ + public class FileFormatNotLegalException : Exception + { + public FileFormatNotLegalException() + { + + } + public override string Message => $"The file is not a legal playback file for THUAI6."; + } + + public class MessageReader : IDisposable + { + private MemoryStream stream; + private CodedInputStream cos; + private GZipStream gzs; + private byte[] buffer; + public bool Finished { get; private set; } = false; + + public readonly uint teamCount; + public readonly uint playerCount; + + const int bufferMaxSize = 10 * 1024 * 1024; // 10M + + public MessageReader(byte[] bytes) + { + stream = new MemoryStream(bytes); + var prefixLen = PlayBackConstant.Prefix.Length; + byte[] bt = new byte[prefixLen + sizeof(UInt32) * 2]; + stream.Read(bt, 0, bt.Length); + for (int i = 0; i < prefixLen; ++i) + { + if (bt[i] != PlayBackConstant.Prefix[i]) throw new FileFormatNotLegalException(); + } + + teamCount = BitConverter.ToUInt32(bt, prefixLen); + playerCount = BitConverter.ToUInt32(bt, prefixLen + sizeof(UInt32)); + + gzs = new GZipStream(stream, CompressionMode.Decompress); + var tmpBuffer = new byte[bufferMaxSize]; + var bufferSize = gzs.Read(tmpBuffer); + if (bufferSize == 0) + { + buffer = tmpBuffer; + Finished = true; + } + else if (bufferSize != bufferMaxSize) // 不留空位,防止 CodedInputStream 获取信息错误 + { + if (bufferSize == 0) + { + Finished = true; + } + buffer = new byte[bufferSize]; + Array.Copy(tmpBuffer, buffer, bufferSize); + } + else + { + buffer = tmpBuffer; + } + cos = new CodedInputStream(buffer); + } + + public MessageToClient? ReadOne() + { + beginRead: + if (Finished) + return null; + var pos = cos.Position; + try + { + MessageToClient? msg = new MessageToClient(); + cos.ReadMessage(msg); + return msg; + } + catch (InvalidProtocolBufferException) + { + var leftByte = buffer.Length - pos; // 上次读取剩余的字节 + if (buffer.Length < bufferMaxSize / 2) + { + var newBuffer = new byte[bufferMaxSize]; + for (int i = 0; i < leftByte; i++) + { + newBuffer[i] = buffer[pos + i]; + } + buffer = newBuffer; + } + else + { + for (int i = 0; i < leftByte; ++i) + { + buffer[i] = buffer[pos + i]; + } + } + var bufferSize = gzs.Read(buffer, (int)leftByte, (int)(buffer.Length - leftByte)) + leftByte; + if (bufferSize == leftByte) + { + Finished = true; + return null; + } + if (bufferSize != buffer.Length) // 不留空位,防止 CodedInputStream 获取信息错误 + { + var tmpBuffer = new byte[bufferSize]; + Array.Copy(buffer, tmpBuffer, bufferSize); + buffer = tmpBuffer; + } + cos = new CodedInputStream(buffer); + goto beginRead; + } + } + + public void Dispose() + { + Finished = true; + if (stream == null) + return; + if (stream.CanRead) + { + stream.Close(); + } + } + + ~MessageReader() + { + Dispose(); + } + } +} \ No newline at end of file diff --git a/interface/interface_playback/Assets/Scripts/Playback/MessageReader.cs.meta b/interface/interface_playback/Assets/Scripts/Playback/MessageReader.cs.meta new file mode 100644 index 00000000..a62ff438 --- /dev/null +++ b/interface/interface_playback/Assets/Scripts/Playback/MessageReader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45bde46b4862fb24e90f28e57c3472ed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/interface/interface_playback/Assets/Scripts/Playback/PlaybackConstant.cs b/interface/interface_playback/Assets/Scripts/Playback/PlaybackConstant.cs new file mode 100644 index 00000000..9db1c411 --- /dev/null +++ b/interface/interface_playback/Assets/Scripts/Playback/PlaybackConstant.cs @@ -0,0 +1,8 @@ +namespace Playback +{ + public static class PlayBackConstant + { + public static string ExtendedName = ".thuaipb"; + public static byte[] Prefix = { (byte)'P', (byte)'B', 7, 0 }; // 文件前缀,用于标识文件类型,版本号为6 + } +} diff --git a/interface/interface_playback/Assets/Scripts/Playback/PlaybackConstant.cs.meta b/interface/interface_playback/Assets/Scripts/Playback/PlaybackConstant.cs.meta new file mode 100644 index 00000000..e3903695 --- /dev/null +++ b/interface/interface_playback/Assets/Scripts/Playback/PlaybackConstant.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3766c4c9813f19748a5a7d8a22a2f080 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/interface/interface_playback/Assets/Scripts/Playback/PlaybackController.cs b/interface/interface_playback/Assets/Scripts/Playback/PlaybackController.cs new file mode 100644 index 00000000..c0188123 --- /dev/null +++ b/interface/interface_playback/Assets/Scripts/Playback/PlaybackController.cs @@ -0,0 +1,223 @@ +using Playback; +using Protobuf; +using System; +using System.Collections; +using UnityEngine; +using UnityEngine.Networking; +using UnityEngine.SceneManagement; + +public class PlaybackController : MonoBehaviour +{ + // Start is called before the first frame update + + public static int studentNum = 4; + private static int classroomNum = 10; + public static int propNum = 10; + public static int hiddenGateNum = 4; + + byte[] bytes = null; + + IEnumerator WebReader(string uri) + { + //if (!fileName.EndsWith(PlayBackConstant.ExtendedName)) + //{ + // fileName += PlayBackConstant.ExtendedName; + //} + //var uri = new Uri(Path.Combine(Application.streamingAssetsPath, fileName)); + //Debug.Log(uri.AbsoluteUri); + + //UnityWebRequest request = UnityWebRequest.Get(uri.AbsoluteUri); + UnityWebRequest request = UnityWebRequest.Get(uri); + request.timeout = 5; + yield return request.SendWebRequest(); + + if (request.isHttpError || request.isNetworkError) + { + Debug.Log(request.error); + filename = null; + playSpeed = 1; + isMap = true; + isInitial = false; + studentScore = trickerScore = 0; + SceneManager.LoadScene("Playback"); + yield break; + } + bytes = request.downloadHandler.data; + } + + void Start() + { + filename = "C:\\Users\\陈宇瀚\\Downloads\\playback.thuaipb"; + StartCoroutine(WebReader(filename)); + timer = frequency; + isMap = true; + isInitial = false; + //StudentController_Playback.studentCount = 0; + //ClassroomProgress_Playback.ClassroomCnt = 0; + } + + // Update is called once per frame + void Update() + { + timer -= Time.deltaTime * playSpeed; + + try + { + if (timer < 0 && bytes != null) + { + if (reader == null) + { + try + { + StopAllCoroutines(); + reader = new MessageReader(bytes); + } + catch (FileFormatNotLegalException) + { + filename = null; + playSpeed = -1; + isMap = true; + isInitial = false; + SceneManager.LoadScene("Playback"); + } + Debug.Log("reader created"); + } + timer = frequency; + var responseVal = reader.ReadOne(); + Debug.Log($"{responseVal}"); + if (responseVal == null) + { + filename = null; + playSpeed = -1; + isMap = true; + isInitial = false; + SceneManager.LoadScene("GameEnd"); + } + else if (isMap) + { + map = responseVal.ObjMessage[0].MapMessage; + isMap = false; + } + else if (!isInitial) + { + Receive(responseVal); + // for (int i = 0; i < studentNum; i++) + // { + // switch (Student[i].StudentType) + // { + // case StudentType.Athlete: + // Instantiate(student1, new Vector3(0f, 0f, 10.0f), new Quaternion(0, 0, 0, 0)); + // Instantiate(student1_icon, new Vector3(60f, -10f * i + 41f, 0), new Quaternion(0, 0, 0, 0)); + // break; + // case StudentType.StraightAStudent: + // Instantiate(student2, new Vector3(0f, 0f, 10.0f), new Quaternion(0, 0, 0, 0)); + // Instantiate(student2_icon, new Vector3(60f, -10f * i + 41f, 0), new Quaternion(0, 0, 0, 0)); + // break; + // case StudentType.Teacher: + // Instantiate(student3, new Vector3(0f, 0f, 10.0f), new Quaternion(0, 0, 0, 0)); + // Instantiate(student3_icon, new Vector3(60f, -10f * i + 41f, 0), new Quaternion(0, 0, 0, 0)); + // break; + // case StudentType.Sunshine: + // Instantiate(student4, new Vector3(0f, 0f, 10.0f), new Quaternion(0, 0, 0, 0)); + // Instantiate(student4_icon, new Vector3(60f, -10f * i + 41f, 0), new Quaternion(0, 0, 0, 0)); + // break; + // case StudentType.TechOtaku: + // Instantiate(student5, new Vector3(0f, 0f, 10.0f), new Quaternion(0, 0, 0, 0)); + // Instantiate(student5_icon, new Vector3(60f, -10f * i + 41f, 0), new Quaternion(0, 0, 0, 0)); + // break; + // case StudentType.Robot: + // Instantiate(student6, new Vector3(0f, 0f, 10.0f), new Quaternion(0, 0, 0, 0)); + // Instantiate(student6_icon, new Vector3(60f, -10f * i + 41f, 0), new Quaternion(0, 0, 0, 0)); + // break; + // default: Instantiate(student1, new Vector3(0f, 0f, 10.0f), new Quaternion(0, 0, 0, 0)); break; + // } + // } + // switch (tricker.TrickerType) + // { + // case TrickerType.Assassin: + // Instantiate(tricker1, new Vector3(0f, 0f, 10.0f), new Quaternion(0, 0, 0, 0)); + // Instantiate(tricker1_icon, new Vector3(60f, 2.7f, 0), new Quaternion(0, 0, 0, 0)); + // break; + // case TrickerType.ANoisyPerson: + // Instantiate(tricker2, new Vector3(0f, 0f, 10.0f), new Quaternion(0, 0, 0, 0)); + // Instantiate(tricker2_icon, new Vector3(60f, 2.7f, 0), new Quaternion(0, 0, 0, 0)); + // break; + // case TrickerType.Klee: + // Instantiate(tricker3, new Vector3(0f, 0f, 10.0f), new Quaternion(0, 0, 0, 0)); + // Instantiate(tricker3_icon, new Vector3(60f, 2.7f, 0), new Quaternion(0, 0, 0, 0)); + // break; + // case TrickerType.Idol: + // Instantiate(tricker1, new Vector3(0f, 0f, 10.0f), new Quaternion(0, 0, 0, 0)); + // Instantiate(tricker1_icon, new Vector3(60f, 2.7f, 0), new Quaternion(0, 0, 0, 0)); + // break; + // default: Instantiate(tricker1, new Vector3(0f, 0f, 10.0f), new Quaternion(0, 0, 0, 0)); break; + // } + isInitial = true; + } + else + { + Receive(responseVal); + } + } + + } + catch (NullReferenceException) + { + filename = null; + playSpeed = 1; + isMap = true; + isInitial = false; + SceneManager.LoadScene("Playback"); + } + + } + + private void Receive(MessageToClient message) + { + int studentCnt = 0; + int classroomCnt = 0; + //Debug.Log(message.ToString()); + time = message.AllMessage.GameTime; + foreach (var messageOfObj in message.ObjMessage) + { + // switch (messageOfObj.MessageOfObjCase) + // { + // case MessageOfObj.MessageOfObjOneofCase.StudentMessage: + // Student[studentCnt] = messageOfObj.StudentMessage; studentCnt++; break; + // case MessageOfObj.MessageOfObjOneofCase.TrickerMessage: + // tricker = messageOfObj.TrickerMessage; break; + // case MessageOfObj.MessageOfObjOneofCase.ClassroomMessage: + // classroom[classroomCnt] = messageOfObj.ClassroomMessage; classroomCnt++; break; + // case MessageOfObj.MessageOfObjOneofCase.PropMessage: + // break; + // case MessageOfObj.MessageOfObjOneofCase.HiddenGateMessage: + // break; + // default: break; + // } + } + } + + public static string filename; + MessageReader reader; + float frequency = 0.05f; + float timer; + public static int playSpeed = 1; + + public static MessageOfMap map; + // public static MessageOfStudent[] Student = new MessageOfStudent[studentNum]; + // public static MessageOfTricker tricker = new MessageOfTricker(); + // public static MessageOfClassroom[] classroom = new MessageOfClassroom[classroomNum]; + // public static MessageOfProp[] prop = new MessageOfProp[propNum]; + // public static MessageOfHiddenGate[] hiddenGate = new MessageOfHiddenGate[hiddenGateNum]; + public GameObject student1, student2, student3, student4, student5, student6; + public GameObject tricker1; + public GameObject tricker2; + public GameObject tricker3; + public GameObject student1_icon, student2_icon, student3_icon, student4_icon, student5_icon, student6_icon; + public GameObject tricker1_icon, tricker2_icon, tricker3_icon; + public static bool isMap; + public static bool isInitial; + public static int time; + public static int studentScore; + public static int trickerScore; +} \ No newline at end of file diff --git a/interface/interface_playback/Assets/Scripts/Playback/PlaybackController.cs.meta b/interface/interface_playback/Assets/Scripts/Playback/PlaybackController.cs.meta new file mode 100644 index 00000000..369f1223 --- /dev/null +++ b/interface/interface_playback/Assets/Scripts/Playback/PlaybackController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ddfe76a77bc0155448788971463b7f57 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/logic/Client/ViewModel/GeneralViewModel.cs b/logic/Client/ViewModel/GeneralViewModel.cs index 05ad23ee..40a5344d 100644 --- a/logic/Client/ViewModel/GeneralViewModel.cs +++ b/logic/Client/ViewModel/GeneralViewModel.cs @@ -1079,7 +1079,7 @@ Show the error message myLogger.LogInfo(String.Format("ip:{0}, port:{1}, playerid:{2}, teamid:{3}, shiptype:{4}, playbackfile:{5}, playbackspeed:{6}", ip, port, playerID, teamID, shipTypeID, playbackFile, playbackSpeed)); //Playback("E:\\program\\Project\\playback.thuaipb", 0.5); - if (playbackFile.Length == 0) + if (string.IsNullOrEmpty(playbackFile)) { try { @@ -1099,14 +1099,15 @@ Show the error message ConnectToServer(comInfo); OnReceive(); } - catch + catch (Exception e) { + myLogger.LogError(e.Message); OnReceive(); } } else { - //myLogger.LogInfo(String.Format("PlaybackFile:{0}", playbackFile)); + myLogger.LogInfo(String.Format("PlaybackFile:{0}", playbackFile)); Playback(playbackFile, playbackSpeed); } //连接Server,comInfo[] 的格式:0 - ip 1 - port 2 - playerID 3 - teamID 4 - ShipType diff --git a/logic/Server/GameServer.cs b/logic/Server/GameServer.cs index a9bd1bf0..886a9482 100755 --- a/logic/Server/GameServer.cs +++ b/logic/Server/GameServer.cs @@ -110,7 +110,7 @@ private void SaveGameResult(string path) } - protected void SendGameResult(int[] scores, bool crashed) // 天梯的 Server 给网站发消息记录比赛结果 + protected void SendGameResult(int[] scores, bool crashed = false) // 天梯的 Server 给网站发消息记录比赛结果 { string? url2 = Environment.GetEnvironmentVariable("FINISH_URL"); if (url2 == null) @@ -229,6 +229,17 @@ private void OnGameEnd() scores = doubleArray.Select(x => (int)x).ToArray(); SendGameResult(scores, crash); } + else if (options.Mode == 1) + { + int[] s = new int[2]; + if (scores[1] > scores[0]) + s = [0, 2]; + else if (scores[1] == scores[0]) + s = [1, 1]; + else + s = [2, 0]; + SendGameResult(s); + } endGameSem.Release(); } public void ReportGame(GameState gameState, bool requiredGaming = true)