| @@ -0,0 +1,24 @@ | |||
| name: build | |||
| on: [push, pull_request] | |||
| jobs: | |||
| dotnet-build: | |||
| runs-on: windows-latest | |||
| steps: | |||
| - uses: actions/checkout@v3 | |||
| - name: Setup .NET Core | |||
| uses: actions/setup-dotnet@v3 | |||
| with: | |||
| dotnet-version: 6.0.x | |||
| - name: Build Logic | |||
| run: dotnet build "./logic/logic.sln" -c Release | |||
| - name: Build Installer | |||
| run: dotnet build "./installer/installer.sln" -c Release | |||
| - name: Build Launcher | |||
| run: dotnet build "./launcher/launcher.sln" -c Release | |||
| - name: Build Playback | |||
| run: dotnet build "./playback/playback.sln" -c Release | |||
| @@ -61,6 +61,13 @@ public: | |||
| virtual bool StartTreatMate() = 0; | |||
| virtual bool StartRescueMate() = 0; | |||
| virtual bool OpenDoor() = 0; | |||
| virtual bool CloseDoor() = 0; | |||
| virtual bool SkipWindow() = 0; | |||
| virtual bool StartOpenGate() = 0; | |||
| virtual bool StartOpenChest() = 0; | |||
| virtual bool EndAllAction() = 0; | |||
| // ITrickerAPI使用的部分 | |||
| virtual bool Attack(double angle) = 0; | |||
| @@ -84,6 +91,14 @@ public: | |||
| virtual std::future<bool> PickProp(THUAI6::PropType prop) = 0; | |||
| virtual std::future<bool> UseProp(THUAI6::PropType prop) = 0; | |||
| virtual std::future<bool> UseSkill(int32_t skillID) = 0; | |||
| virtual std::future<bool> Attack(double angleInRadian) = 0; | |||
| virtual std::future<bool> OpenDoor() = 0; | |||
| virtual std::future<bool> CloseDoor() = 0; | |||
| virtual std::future<bool> SkipWindow() = 0; | |||
| virtual std::future<bool> StartOpenGate() = 0; | |||
| virtual std::future<bool> StartOpenChest() = 0; | |||
| virtual std::future<bool> EndAllAction() = 0; | |||
| // 发送信息、接受信息,注意收消息时无消息则返回nullopt | |||
| virtual std::future<bool> SendMessage(int64_t, std::string) = 0; | |||
| @@ -149,7 +164,6 @@ class ITrickerAPI : public IAPI | |||
| public: | |||
| /*****捣蛋鬼阵营的特定函数*****/ | |||
| virtual std::future<bool> Attack(double angleInRadian) = 0; | |||
| [[nodiscard]] virtual std::shared_ptr<const THUAI6::Tricker> GetSelfInfo() const = 0; | |||
| }; | |||
| @@ -190,6 +204,15 @@ public: | |||
| std::future<bool> UseProp(THUAI6::PropType prop) override; | |||
| std::future<bool> UseSkill(int32_t skillID) override; | |||
| std::future<bool> Attack(double angleInRadian) override; | |||
| std::future<bool> OpenDoor() override; | |||
| std::future<bool> CloseDoor() override; | |||
| std::future<bool> SkipWindow() override; | |||
| std::future<bool> StartOpenGate() override; | |||
| std::future<bool> StartOpenChest() override; | |||
| std::future<bool> EndAllAction() override; | |||
| std::future<bool> SendMessage(int64_t, std::string) override; | |||
| [[nodiscard]] std::future<bool> HaveMessage() override; | |||
| [[nodiscard]] std::future<std::optional<std::pair<int64_t, std::string>>> GetMessage() override; | |||
| @@ -256,6 +279,13 @@ public: | |||
| std::future<bool> UseProp(THUAI6::PropType prop) override; | |||
| std::future<bool> UseSkill(int32_t skillID) override; | |||
| std::future<bool> OpenDoor() override; | |||
| std::future<bool> CloseDoor() override; | |||
| std::future<bool> SkipWindow() override; | |||
| std::future<bool> StartOpenGate() override; | |||
| std::future<bool> StartOpenChest() override; | |||
| std::future<bool> EndAllAction() override; | |||
| std::future<bool> SendMessage(int64_t, std::string) override; | |||
| [[nodiscard]] std::future<bool> HaveMessage() override; | |||
| [[nodiscard]] std::future<std::optional<std::pair<int64_t, std::string>>> GetMessage() override; | |||
| @@ -312,6 +342,15 @@ public: | |||
| std::future<bool> UseProp(THUAI6::PropType prop) override; | |||
| std::future<bool> UseSkill(int32_t skillID) override; | |||
| std::future<bool> Attack(double angleInRadian) override; | |||
| std::future<bool> OpenDoor() override; | |||
| std::future<bool> CloseDoor() override; | |||
| std::future<bool> SkipWindow() override; | |||
| std::future<bool> StartOpenGate() override; | |||
| std::future<bool> StartOpenChest() override; | |||
| std::future<bool> EndAllAction() override; | |||
| std::future<bool> SendMessage(int64_t, std::string) override; | |||
| [[nodiscard]] std::future<bool> HaveMessage() override; | |||
| [[nodiscard]] std::future<std::optional<std::pair<int64_t, std::string>>> GetMessage() override; | |||
| @@ -365,6 +404,13 @@ public: | |||
| std::future<bool> UseProp(THUAI6::PropType prop) override; | |||
| std::future<bool> UseSkill(int32_t skillID) override; | |||
| std::future<bool> OpenDoor() override; | |||
| std::future<bool> CloseDoor() override; | |||
| std::future<bool> SkipWindow() override; | |||
| std::future<bool> StartOpenGate() override; | |||
| std::future<bool> StartOpenChest() override; | |||
| std::future<bool> EndAllAction() override; | |||
| std::future<bool> SendMessage(int64_t, std::string) override; | |||
| [[nodiscard]] std::future<bool> HaveMessage() override; | |||
| [[nodiscard]] std::future<std::optional<std::pair<int64_t, std::string>>> GetMessage() override; | |||
| @@ -118,6 +118,13 @@ private: | |||
| bool Attack(double angle) override; | |||
| bool OpenDoor() override; | |||
| bool CloseDoor() override; | |||
| bool SkipWindow() override; | |||
| bool StartOpenGate() override; | |||
| bool StartOpenChest() override; | |||
| bool EndAllAction() override; | |||
| bool WaitThread() override; | |||
| int GetCounter() const override; | |||
| @@ -101,6 +101,78 @@ std::future<bool> TrickerAPI::UseSkill(int32_t skillID) | |||
| { return logic.UseSkill(skillID); }); | |||
| } | |||
| std::future<bool> StudentAPI::OpenDoor() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.OpenDoor(); }); | |||
| } | |||
| std::future<bool> TrickerAPI::OpenDoor() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.OpenDoor(); }); | |||
| } | |||
| std::future<bool> StudentAPI::CloseDoor() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.CloseDoor(); }); | |||
| } | |||
| std::future<bool> TrickerAPI::CloseDoor() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.CloseDoor(); }); | |||
| } | |||
| std::future<bool> StudentAPI::SkipWindow() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.SkipWindow(); }); | |||
| } | |||
| std::future<bool> TrickerAPI::SkipWindow() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.SkipWindow(); }); | |||
| } | |||
| std::future<bool> StudentAPI::StartOpenGate() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.StartOpenGate(); }); | |||
| } | |||
| std::future<bool> TrickerAPI::StartOpenGate() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.StartOpenGate(); }); | |||
| } | |||
| std::future<bool> StudentAPI::StartOpenChest() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.StartOpenChest(); }); | |||
| } | |||
| std::future<bool> TrickerAPI::StartOpenChest() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.StartOpenChest(); }); | |||
| } | |||
| std::future<bool> StudentAPI::EndAllAction() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.EndAllAction(); }); | |||
| } | |||
| std::future<bool> TrickerAPI::EndAllAction() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.EndAllAction(); }); | |||
| } | |||
| std::future<bool> StudentAPI::SendMessage(int64_t toID, std::string message) | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| @@ -252,6 +324,12 @@ std::future<bool> TrickerAPI::Attack(double angleInRadian) | |||
| { return logic.Attack(angleInRadian); }); | |||
| } | |||
| std::future<bool> StudentAPI::Attack(double angleInRadian) | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.Attack(angleInRadian); }); | |||
| } | |||
| std::shared_ptr<const THUAI6::Tricker> TrickerAPI::GetSelfInfo() const | |||
| { | |||
| return logic.TrickerGetSelfInfo(); | |||
| @@ -206,6 +206,78 @@ std::future<bool> TrickerDebugAPI::UseSkill(int32_t skillID) | |||
| return result; }); | |||
| } | |||
| std::future<bool> StudentDebugAPI::OpenDoor() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.OpenDoor(); }); | |||
| } | |||
| std::future<bool> TrickerDebugAPI::OpenDoor() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.OpenDoor(); }); | |||
| } | |||
| std::future<bool> StudentDebugAPI::CloseDoor() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.CloseDoor(); }); | |||
| } | |||
| std::future<bool> TrickerDebugAPI::CloseDoor() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.CloseDoor(); }); | |||
| } | |||
| std::future<bool> StudentDebugAPI::SkipWindow() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.SkipWindow(); }); | |||
| } | |||
| std::future<bool> TrickerDebugAPI::SkipWindow() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.SkipWindow(); }); | |||
| } | |||
| std::future<bool> StudentDebugAPI::StartOpenGate() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.StartOpenGate(); }); | |||
| } | |||
| std::future<bool> TrickerDebugAPI::StartOpenGate() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.StartOpenGate(); }); | |||
| } | |||
| std::future<bool> StudentDebugAPI::StartOpenChest() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.StartOpenChest(); }); | |||
| } | |||
| std::future<bool> TrickerDebugAPI::StartOpenChest() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.StartOpenChest(); }); | |||
| } | |||
| std::future<bool> StudentDebugAPI::EndAllAction() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.EndAllAction(); }); | |||
| } | |||
| std::future<bool> TrickerDebugAPI::EndAllAction() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.EndAllAction(); }); | |||
| } | |||
| std::future<bool> StudentDebugAPI::SendMessage(int64_t toID, std::string message) | |||
| { | |||
| logger->info("SendMessage: toID = {}, message = {}, called at {}ms", toID, message, Time::TimeSinceStart(startPoint)); | |||
| @@ -403,6 +475,16 @@ std::future<bool> TrickerDebugAPI::Attack(double angleInRadian) | |||
| return result; }); | |||
| } | |||
| std::future<bool> StudentDebugAPI::Attack(double angleInRadian) | |||
| { | |||
| logger->info("Attack: angleInRadian = {}, called at {}ms", angleInRadian, Time::TimeSinceStart(startPoint)); | |||
| return std::async(std::launch::async, [=]() | |||
| { auto result = logic.Attack(angleInRadian); | |||
| if (!result) | |||
| logger->warn("Attack: failed at {}ms", Time::TimeSinceStart(startPoint)); | |||
| return result; }); | |||
| } | |||
| std::shared_ptr<const THUAI6::Tricker> TrickerDebugAPI::GetSelfInfo() const | |||
| { | |||
| return logic.TrickerGetSelfInfo(); | |||
| @@ -147,6 +147,42 @@ bool Logic::Attack(double angle) | |||
| return pComm->Attack(angle, playerID); | |||
| } | |||
| bool Logic::OpenDoor() | |||
| { | |||
| logger->debug("Called OpenDoor"); | |||
| return pComm->OpenDoor(playerID); | |||
| } | |||
| bool Logic::CloseDoor() | |||
| { | |||
| logger->debug("Called CloseDoor"); | |||
| return pComm->CloseDoor(playerID); | |||
| } | |||
| bool Logic::SkipWindow() | |||
| { | |||
| logger->debug("Called SkipWindow"); | |||
| return pComm->SkipWindow(playerID); | |||
| } | |||
| bool Logic::StartOpenGate() | |||
| { | |||
| logger->debug("Called StartOpenGate"); | |||
| return pComm->StartOpenGate(playerID); | |||
| } | |||
| bool Logic::StartOpenChest() | |||
| { | |||
| logger->debug("Called StartOpenChest"); | |||
| return pComm->StartOpenChest(playerID); | |||
| } | |||
| bool Logic::EndAllAction() | |||
| { | |||
| logger->debug("Called EndAllAction"); | |||
| return pComm->EndAllAction(playerID); | |||
| } | |||
| bool Logic::WaitThread() | |||
| { | |||
| Update(); | |||
| @@ -1,10 +1,15 @@ | |||
| # THUAI6 | |||
| 清华大学第六届人工智能挑战赛电子系赛道(原电子系第 24 届队式程序设计大赛 teamstyle24) | |||
| Gitee 镜像地址:[THUAI6: Gitee Mirror](https://gitee.com/eesast/THUAI6) | |||
| GitLink 镜像地址:[THUAI6: GitLink Mirror](https://www.gitlink.org.cn/EESAST/THUAI6) | |||
| 项目主页:[THUAI6 Project Home Page](https://eesast.github.io/THUAI6) | |||
| 关于本届及历届清华大学人工智能挑战赛与队式程序设计大赛的更多内容参见:[THUAI6 Github Wiki](https://github.com/eesast/THUAI6/wiki) | |||
| ## 赛题背景 | |||
| 待定 | |||
| @@ -10,8 +10,8 @@ message MessageOfStudent | |||
| int32 y = 2; | |||
| int32 speed = 3; | |||
| int32 determination = 4; // 剩余的学习毅力,相当于血量 | |||
| int32 fail_num = 5; // 挂科的科目数 | |||
| double time_until_skill_available = 6; | |||
| //int32 fail_num = 5; // 挂科的科目数 | |||
| repeated double time_until_skill_available = 6; | |||
| PlaceType place = 7; | |||
| repeated PropType prop = 8; | |||
| PlayerState player_state = 9; | |||
| @@ -142,7 +142,6 @@ message MessageOfMap | |||
| repeated PlaceType col = 1; | |||
| } | |||
| repeated Row row = 2; | |||
| repeated MessageOfMapObj map_obj_message = 3; | |||
| } | |||
| message MessageOfObj | |||
| @@ -154,6 +153,7 @@ message MessageOfObj | |||
| MessageOfProp prop_message = 3; | |||
| MessageOfBullet bullet_message = 4; | |||
| MessageOfBombedBullet bombed_bullet_message = 5; | |||
| MessageOfMapObj map_obj_message = 6; | |||
| } | |||
| } | |||
| @@ -7,56 +7,48 @@ import "MessageType.proto"; | |||
| message PlayerMsg | |||
| { | |||
| int64 player_id = 1; | |||
| PlayerType player_type = 2; | |||
| oneof job_type | |||
| { | |||
| StudentType student_type = 3; | |||
| TrickerType tricker_type = 4; | |||
| StudentType student_type = 2; | |||
| TrickerType tricker_type = 3; | |||
| } | |||
| } | |||
| message MoveMsg | |||
| { | |||
| int64 player_id = 1; | |||
| PlayerType player_type = 2; | |||
| double angle = 3; | |||
| int64 time_in_milliseconds = 4; | |||
| double angle = 2; | |||
| int64 time_in_milliseconds = 3; | |||
| } | |||
| message PropMsg | |||
| { | |||
| int64 player_id = 1; | |||
| PlayerType player_type = 2; | |||
| PropType prop_type = 3; | |||
| PropType prop_type = 2; | |||
| } | |||
| message SendMsg | |||
| { | |||
| int64 player_id = 1; | |||
| PlayerType player_type = 2; | |||
| int64 to_player_id = 3; | |||
| PlayerType to_player_type = 4; | |||
| string message = 5; | |||
| int64 to_player_id = 2; | |||
| string message = 3; | |||
| } | |||
| message AttackMsg // 相当于攻击 | |||
| { | |||
| int64 player_id = 1; | |||
| PlayerType player_type = 2; | |||
| double angle = 3; | |||
| double angle = 2; | |||
| } | |||
| message IDMsg | |||
| { | |||
| int64 player_id = 1; | |||
| PlayerType player_type = 2; | |||
| } | |||
| message SkillMsg | |||
| { | |||
| int64 player_id = 1; | |||
| PlayerType player_type = 2; | |||
| int32 skill_id = 3; | |||
| int32 skill_id = 2; | |||
| } | |||
| // 基本继承于THUAI5,为了使发送的信息尽可能不被浪费,暂定不发这类大包。 | |||
| @@ -12,12 +12,10 @@ namespace ClientTest | |||
| var client = new AvailableService.AvailableServiceClient(channel); | |||
| PlayerMsg playerInfo = new(); | |||
| playerInfo.PlayerId = 0; | |||
| playerInfo.PlayerType = PlayerType.StudentPlayer; | |||
| playerInfo.StudentType = StudentType.NullStudentType; | |||
| var call = client.AddPlayer(playerInfo); | |||
| MoveMsg moveMsg = new(); | |||
| moveMsg.PlayerId = 0; | |||
| moveMsg.PlayerType = PlayerType.StudentPlayer; | |||
| moveMsg.TimeInMilliseconds = 100; | |||
| moveMsg.Angle = 0; | |||
| while (true) | |||
| @@ -29,15 +27,15 @@ namespace ClientTest | |||
| while (await call.ResponseStream.MoveNext()) | |||
| { | |||
| Console.WriteLine("hi"); | |||
| var currentGameInfo = call.ResponseStream.Current; | |||
| if (playerInfo.PlayerType == PlayerType.StudentPlayer) | |||
| for (int i = 0; i < currentGameInfo.ObjMessage.Count; i++) | |||
| { | |||
| for (int i = 0; i < currentGameInfo.ObjMessage.Count; i++) | |||
| { | |||
| //Console.WriteLine($"Human is at ({currentGameInfo.StudentMessage[i].X}, {currentGameInfo.StudentMessage[i].Y})"); | |||
| } | |||
| if (currentGameInfo.ObjMessage[i].MessageOfObjCase == MessageOfObj.MessageOfObjOneofCase.StudentMessage) | |||
| Console.WriteLine($"Human is at ({currentGameInfo.ObjMessage[i].StudentMessage.X}, {currentGameInfo.ObjMessage[i].StudentMessage.Y})"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -179,6 +179,7 @@ namespace Gaming | |||
| propManager.StartProducing(); | |||
| // 开始游戏 | |||
| new Thread | |||
| ( | |||
| () => | |||
| @@ -8,13 +8,14 @@ namespace Server | |||
| public static class CopyInfo | |||
| { | |||
| // 下面赋值为0的大概率是还没写完 2023-03-03 | |||
| /*public static MessageOfObj? Auto(GameObj gameObj) | |||
| public static MessageOfObj? Auto(GameObj gameObj) | |||
| { | |||
| if (gameObj.Type == Preparation.Utility.GameObjType.Character) | |||
| { | |||
| Character character = (Character)gameObj; | |||
| if (character.IsGhost()) | |||
| return Tri | |||
| return Tricker((Character)character); | |||
| else return Student((Character)character); | |||
| } | |||
| else if (gameObj.Type == Preparation.Utility.GameObjType.Bullet) | |||
| return Bullet((Bullet)gameObj); | |||
| @@ -25,28 +26,34 @@ namespace Server | |||
| else if (gameObj.Type == Preparation.Utility.GameObjType.PickedProp) | |||
| return PickedProp((PickedProp)gameObj); | |||
| else return null; //先写着防报错 | |||
| }*/ | |||
| } | |||
| private static MessageOfStudent? Student(Character player) | |||
| private static MessageOfObj? Student(Character player) | |||
| { | |||
| MessageOfStudent msg = new MessageOfStudent(); | |||
| MessageOfObj msg = new MessageOfObj(); | |||
| if (player.IsGhost()) return null; | |||
| msg.StudentMessage = new(); | |||
| msg.X = player.Position.x; | |||
| msg.Y = player.Position.y; | |||
| msg.Speed = player.MoveSpeed; | |||
| msg.Determination = player.HP; | |||
| msg.FailNum = 0; | |||
| msg.TimeUntilSkillAvailable = 0; | |||
| msg.StudentType = StudentType.NullStudentType; // 下面写 | |||
| msg.Guid = 0; | |||
| msg.State = StudentState.NullStatus; | |||
| msg.FailTime = 0; | |||
| msg.EmoTime = 0; | |||
| msg.PlayerId = 0; | |||
| msg.ViewRange = 0; | |||
| msg.Radius = 0; | |||
| msg.StudentMessage.X = player.Position.x; | |||
| msg.StudentMessage.Y = player.Position.y; | |||
| msg.StudentMessage.Speed = player.MoveSpeed; | |||
| msg.StudentMessage.Determination = player.HP; | |||
| //msg.StudentMessage.FailNum = 0; | |||
| foreach (var keyValue in player.TimeUntilActiveSkillAvailable) | |||
| msg.StudentMessage.TimeUntilSkillAvailable.Add(keyValue.Value); | |||
| //msg.StudentMessage.StudentType; // 下面写 | |||
| msg.StudentMessage.Guid = player.ID; | |||
| // msg.StudentMessage.State = player.PlayerState; | |||
| msg.StudentMessage.FailTime = 0; | |||
| msg.StudentMessage.EmoTime = 0; | |||
| msg.StudentMessage.PlayerId = 0; | |||
| msg.StudentMessage.ViewRange = 0; | |||
| msg.StudentMessage.Radius = 0; | |||
| msg.StudentMessage.Damage = 0; | |||
| msg.StudentMessage.DangerAlert = 0; | |||
| msg.StudentMessage.Score = 0; | |||
| msg.StudentMessage.TreatProgress = 0; | |||
| msg.StudentMessage.RescueProgress = 0; | |||
| foreach (KeyValuePair<Preparation.Utility.BuffType, bool> kvp in player.Buff) | |||
| { | |||
| @@ -55,178 +62,77 @@ namespace Server | |||
| switch (kvp.Key) // StudentBuffType具体内容待定 | |||
| { | |||
| case Preparation.Utility.BuffType.Spear: | |||
| msg.Buff.Add(StudentBuffType.NullSbuffType); | |||
| msg.StudentMessage.Buff.Add(StudentBuffType.NullSbuffType); | |||
| break; | |||
| case Preparation.Utility.BuffType.AddLIFE: | |||
| msg.Buff.Add(StudentBuffType.NullSbuffType); | |||
| msg.StudentMessage.Buff.Add(StudentBuffType.NullSbuffType); | |||
| break; | |||
| case Preparation.Utility.BuffType.Shield: | |||
| msg.Buff.Add(StudentBuffType.NullSbuffType); | |||
| msg.StudentMessage.Buff.Add(StudentBuffType.NullSbuffType); | |||
| break; | |||
| case Preparation.Utility.BuffType.AddSpeed: | |||
| msg.Buff.Add(StudentBuffType.NullSbuffType); | |||
| msg.StudentMessage.Buff.Add(StudentBuffType.NullSbuffType); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| switch (player.Place) | |||
| { | |||
| case Preparation.Utility.PlaceType.EmergencyExit: | |||
| msg.Place = PlaceType.HiddenGate; | |||
| break; | |||
| case Preparation.Utility.PlaceType.Doorway: | |||
| msg.Place = PlaceType.Gate; | |||
| break; | |||
| case Preparation.Utility.PlaceType.Grass: | |||
| msg.Place = PlaceType.Grass; | |||
| break; | |||
| case Preparation.Utility.PlaceType.BirthPoint1: | |||
| case Preparation.Utility.PlaceType.BirthPoint2: | |||
| case Preparation.Utility.PlaceType.BirthPoint3: | |||
| case Preparation.Utility.PlaceType.BirthPoint4: | |||
| case Preparation.Utility.PlaceType.BirthPoint5: | |||
| case Preparation.Utility.PlaceType.Null: | |||
| msg.Place = PlaceType.Land; | |||
| break; | |||
| // case Preparation.Utility.PlaceType.Invisible: | |||
| // msg.MessageOfHuman.Place = Communication.Proto.PlaceType.Invisible; | |||
| // break; | |||
| default: | |||
| msg.Place = PlaceType.NullPlaceType; | |||
| break; | |||
| } | |||
| //Character的储存方式可能得改,用enum type存道具和子弹,不应该用对象 | |||
| //现在懒得改了,有时间再重整一波 | |||
| if (player.PropInventory == null) | |||
| msg.Prop.Add(PropType.NullPropType); | |||
| msg.StudentMessage.Prop.Add(PropType.NullPropType); | |||
| else | |||
| { | |||
| switch (player.PropInventory.GetPropType()) | |||
| { | |||
| case Preparation.Utility.PropType.Gem: | |||
| msg.Prop.Add(PropType.NullPropType); | |||
| msg.StudentMessage.Prop.Add(PropType.NullPropType); | |||
| break; | |||
| /*case Preparation.Utility.PropType.addLIFE: | |||
| msg.MessageOfHuman.Prop = Communication.Proto.PropType.AddLife; | |||
| msg.StudentMessage.MessageOfHuman.Prop = Communication.Proto.PropType.AddLife; | |||
| break; | |||
| case Preparation.Utility.PropType.addSpeed: | |||
| msg.MessageOfHuman.Prop = Communication.Proto.PropType.AddSpeed; | |||
| msg.StudentMessage.MessageOfHuman.Prop = Communication.Proto.PropType.AddSpeed; | |||
| break; | |||
| case Preparation.Utility.PropType.Shield: | |||
| msg.MessageOfHuman.Prop = Communication.Proto.PropType.Shield; | |||
| msg.StudentMessage.MessageOfHuman.Prop = Communication.Proto.PropType.Shield; | |||
| break; | |||
| case Preparation.Utility.PropType.Spear: | |||
| msg.MessageOfHuman.Prop = Communication.Proto.PropType.Spear; | |||
| msg.StudentMessage.MessageOfHuman.Prop = Communication.Proto.PropType.Spear; | |||
| break; | |||
| default: | |||
| msg.Prop = PropType.NullPropType; | |||
| msg.StudentMessage.Prop = PropType.NullPropType; | |||
| break;*/ | |||
| } | |||
| } | |||
| /*switch (player.PassiveSkillType) 需要对接一下,proto里似乎没有这个 | |||
| { | |||
| case Preparation.Utility.PassiveSkillType.RecoverAfterBattle: | |||
| msg.MessageOfHuman.PassiveSkillType = Communication.Proto.PassiveSkillType.RecoverAfterBattle; | |||
| break; | |||
| case Preparation.Utility.PassiveSkillType.SpeedUpWhenLeavingGrass: | |||
| msg.MessageOfHuman.PassiveSkillType = Communication.Proto.PassiveSkillType.SpeedUpWhenLeavingGrass; | |||
| break; | |||
| case Preparation.Utility.PassiveSkillType.Vampire: | |||
| msg.MessageOfHuman.PassiveSkillType = Communication.Proto.PassiveSkillType.Vampire; | |||
| break; | |||
| default: | |||
| msg.MessageOfHuman.PassiveSkillType = Communication.Proto.PassiveSkillType.NullPassiveSkillType; | |||
| break; | |||
| } | |||
| switch (player.CommonSkillType) | |||
| { | |||
| case Preparation.Utility.ActiveSkillType.BecomeAssassin: | |||
| msg.MessageOfHuman.ActiveSkillType = Communication.Proto.ActiveSkillType.BecomeAssassin; | |||
| break; | |||
| case Preparation.Utility.ActiveSkillType.BecomeVampire: | |||
| msg.MessageOfHuman.ActiveSkillType = Communication.Proto.ActiveSkillType.BecomeVampire; | |||
| break; | |||
| case Preparation.Utility.ActiveSkillType.NuclearWeapon: | |||
| msg.MessageOfHuman.ActiveSkillType = Communication.Proto.ActiveSkillType.NuclearWeapon; | |||
| break; | |||
| case Preparation.Utility.ActiveSkillType.SuperFast: | |||
| msg.MessageOfHuman.ActiveSkillType = Communication.Proto.ActiveSkillType.SuperFast; | |||
| break; | |||
| default: | |||
| msg.MessageOfHuman.ActiveSkillType = Communication.Proto.ActiveSkillType.NullActiveSkillType; | |||
| break; | |||
| } | |||
| switch (player.BulletOfPlayer) | |||
| { | |||
| case Preparation.Utility.BulletType.AtomBomb: | |||
| msg.MessageOfHuman.BulletType = Communication.Proto.BulletType.AtomBomb; | |||
| break; | |||
| case Preparation.Utility.BulletType.OrdinaryBullet: | |||
| msg.MessageOfHuman.BulletType = Communication.Proto.BulletType.OrdinaryBullet; | |||
| break; | |||
| case Preparation.Utility.BulletType.FastBullet: | |||
| msg.MessageOfHuman.BulletType = Communication.Proto.BulletType.FastBullet; | |||
| break; | |||
| case Preparation.Utility.BulletType.LineBullet: | |||
| msg.MessageOfHuman.BulletType = Communication.Proto.BulletType.LineBullet; | |||
| break; | |||
| default: | |||
| msg.MessageOfHuman.BulletType = Communication.Proto.BulletType.NullBulletType; | |||
| break; | |||
| }*/ | |||
| return msg; | |||
| } | |||
| private static MessageOfTricker? Butcher(Character player) | |||
| private static MessageOfObj? Tricker(Character player) | |||
| { | |||
| MessageOfTricker msg = new MessageOfTricker(); | |||
| MessageOfObj msg = new MessageOfObj(); | |||
| if (!player.IsGhost()) return null; | |||
| msg.TrickerMessage = new(); | |||
| msg.X = player.Position.x; | |||
| msg.Y = player.Position.y; | |||
| msg.Speed = player.MoveSpeed; | |||
| msg.Damage = 0; | |||
| msg.TimeUntilSkillAvailable = 0; | |||
| //msg.Place = 0; 下面写了 | |||
| //msg.Prop = PropType.NullPropType; // 下面写 | |||
| msg.TrickerType = TrickerType.NullTrickerType; // 下面写 | |||
| msg.Guid = 0; | |||
| msg.Movable = false; | |||
| msg.PlayerId = 0; | |||
| msg.ViewRange = 0; | |||
| msg.Radius = 0; | |||
| //msg.Buff[0] = ButcherBuffType.NullSbuffType; 下面写了 | |||
| /* THUAI5中的内容 | |||
| msg.BulletNum = player.BulletNum; | |||
| msg.CanMove = player.CanMove; | |||
| msg.CD = player.CD; | |||
| msg.GemNum = player.GemNum; | |||
| msg.Guid = player.ID; | |||
| msg.IsDeceased = player.IsDeceased; | |||
| msg.LifeNum = player.DeathCount + 1; | |||
| msg.Radius = player.Radius; | |||
| msg.TimeUntilCommonSkillAvailable = player.TimeUntilCommonSkillAvailable; | |||
| msg.TeamID = player.TeamID; | |||
| msg.PlayerID = player.PlayerID; | |||
| msg.IsInvisible = player.IsInvisible; | |||
| msg.FacingDirection = player.FacingDirection; | |||
| msg.TrickerMessage.X = player.Position.x; | |||
| msg.TrickerMessage.Y = player.Position.y; | |||
| msg.TrickerMessage.Speed = player.MoveSpeed; | |||
| msg.TrickerMessage.Damage = 0; | |||
| msg.TrickerMessage.TimeUntilSkillAvailable = 0; | |||
| //msg.TrickerMessage.Place = 0; 下面写了 | |||
| //msg.TrickerMessage.Prop = PropType.NullPropType; // 下面写 | |||
| msg.TrickerMessage.TrickerType = TrickerType.NullTrickerType; // 下面写 | |||
| msg.TrickerMessage.Guid = 0; | |||
| msg.TrickerMessage.Movable = false; | |||
| msg.TrickerMessage.PlayerId = 0; | |||
| msg.TrickerMessage.ViewRange = 0; | |||
| msg.TrickerMessage.Radius = 0; | |||
| //msg.TrickerMessage.Buff[0] = ButcherBuffType.NullSbuffType; 下面写了 | |||
| //应该要发队伍分数,这里先发个人分数 | |||
| msg.MessageOfHuman.Score = player.Score; | |||
| //这条暂时没啥用 | |||
| msg.MessageOfHuman.TimeUntilUltimateSkillAvailable = 0; | |||
| msg.MessageOfHuman.Vampire = player.Vampire;*/ | |||
| foreach (KeyValuePair<Preparation.Utility.BuffType, bool> kvp in player.Buff) | |||
| { | |||
| @@ -235,16 +141,16 @@ namespace Server | |||
| switch (kvp.Key) // ButcherBuffType具体内容待定 | |||
| { | |||
| case Preparation.Utility.BuffType.Spear: | |||
| msg.Buff.Add(TrickerBuffType.NullTbuffType); | |||
| msg.TrickerMessage.Buff.Add(TrickerBuffType.NullTbuffType); | |||
| break; | |||
| case Preparation.Utility.BuffType.AddLIFE: | |||
| msg.Buff.Add(TrickerBuffType.NullTbuffType); | |||
| msg.TrickerMessage.Buff.Add(TrickerBuffType.NullTbuffType); | |||
| break; | |||
| case Preparation.Utility.BuffType.Shield: | |||
| msg.Buff.Add(TrickerBuffType.NullTbuffType); | |||
| msg.TrickerMessage.Buff.Add(TrickerBuffType.NullTbuffType); | |||
| break; | |||
| case Preparation.Utility.BuffType.AddSpeed: | |||
| msg.Buff.Add(TrickerBuffType.NullTbuffType); | |||
| msg.TrickerMessage.Buff.Add(TrickerBuffType.NullTbuffType); | |||
| break; | |||
| default: | |||
| break; | |||
| @@ -254,261 +160,207 @@ namespace Server | |||
| /*switch (player.Place) | |||
| { | |||
| case Preparation.Utility.PlaceType.Land: | |||
| msg.Place = PlaceType.Land; | |||
| msg.TrickerMessage.Place = PlaceType.Land; | |||
| break; | |||
| case Preparation.Utility.PlaceType.Grass1: | |||
| msg.Place = PlaceType.Grass; | |||
| msg.TrickerMessage.Place = PlaceType.Grass; | |||
| break; | |||
| case Preparation.Utility.PlaceType.Grass2: | |||
| msg.Place = PlaceType.Grass; | |||
| msg.TrickerMessage.Place = PlaceType.Grass; | |||
| break; | |||
| case Preparation.Utility.PlaceType.Grass3: | |||
| msg.Place = PlaceType.Grass; | |||
| msg.TrickerMessage.Place = PlaceType.Grass; | |||
| break; | |||
| // case Preparation.Utility.PlaceType.Invisible: | |||
| // msg.MessageOfHuman.Place = Communication.Proto.PlaceType.Invisible; | |||
| // msg.TrickerMessage.MessageOfHuman.Place = Communication.Proto.PlaceType.Invisible; | |||
| // break; | |||
| default: | |||
| msg.Place = PlaceType.NullPlaceType; | |||
| msg.TrickerMessage.Place = PlaceType.NullPlaceType; | |||
| break; | |||
| }*/ | |||
| //Character的储存方式可能得改,用enum type存道具和子弹,不应该用对象 | |||
| //现在懒得改了,有时间再重整一波 | |||
| /*if (player.PropInventory == null) | |||
| msg.Prop = PropType.NullPropType; | |||
| msg.TrickerMessage.Prop = PropType.NullPropType; | |||
| else | |||
| { | |||
| switch (player.PropInventory.GetPropType()) | |||
| { | |||
| case Preparation.Utility.PropType.Gem: | |||
| msg.Prop = PropType.NullPropType; | |||
| msg.TrickerMessage.Prop = PropType.NullPropType; | |||
| break; | |||
| case Preparation.Utility.PropType.addLIFE: | |||
| msg.MessageOfHuman.Prop = Communication.Proto.PropType.AddLife; | |||
| msg.TrickerMessage.MessageOfHuman.Prop = Communication.Proto.PropType.AddLife; | |||
| break; | |||
| case Preparation.Utility.PropType.addSpeed: | |||
| msg.MessageOfHuman.Prop = Communication.Proto.PropType.AddSpeed; | |||
| msg.TrickerMessage.MessageOfHuman.Prop = Communication.Proto.PropType.AddSpeed; | |||
| break; | |||
| case Preparation.Utility.PropType.Shield: | |||
| msg.MessageOfHuman.Prop = Communication.Proto.PropType.Shield; | |||
| msg.TrickerMessage.MessageOfHuman.Prop = Communication.Proto.PropType.Shield; | |||
| break; | |||
| case Preparation.Utility.PropType.Spear: | |||
| msg.MessageOfHuman.Prop = Communication.Proto.PropType.Spear; | |||
| msg.TrickerMessage.MessageOfHuman.Prop = Communication.Proto.PropType.Spear; | |||
| break; | |||
| default: | |||
| msg.Prop = PropType.NullPropType; | |||
| msg.TrickerMessage.Prop = PropType.NullPropType; | |||
| break; | |||
| } | |||
| }*/ | |||
| /*switch (player.PassiveSkillType) 需要对接一下,proto里似乎没有这个 | |||
| { | |||
| case Preparation.Utility.PassiveSkillType.RecoverAfterBattle: | |||
| msg.MessageOfHuman.PassiveSkillType = Communication.Proto.PassiveSkillType.RecoverAfterBattle; | |||
| break; | |||
| case Preparation.Utility.PassiveSkillType.SpeedUpWhenLeavingGrass: | |||
| msg.MessageOfHuman.PassiveSkillType = Communication.Proto.PassiveSkillType.SpeedUpWhenLeavingGrass; | |||
| break; | |||
| case Preparation.Utility.PassiveSkillType.Vampire: | |||
| msg.MessageOfHuman.PassiveSkillType = Communication.Proto.PassiveSkillType.Vampire; | |||
| break; | |||
| default: | |||
| msg.MessageOfHuman.PassiveSkillType = Communication.Proto.PassiveSkillType.NullPassiveSkillType; | |||
| break; | |||
| } | |||
| switch (player.CommonSkillType) | |||
| { | |||
| case Preparation.Utility.ActiveSkillType.BecomeAssassin: | |||
| msg.MessageOfHuman.ActiveSkillType = Communication.Proto.ActiveSkillType.BecomeAssassin; | |||
| break; | |||
| case Preparation.Utility.ActiveSkillType.BecomeVampire: | |||
| msg.MessageOfHuman.ActiveSkillType = Communication.Proto.ActiveSkillType.BecomeVampire; | |||
| break; | |||
| case Preparation.Utility.ActiveSkillType.NuclearWeapon: | |||
| msg.MessageOfHuman.ActiveSkillType = Communication.Proto.ActiveSkillType.NuclearWeapon; | |||
| break; | |||
| case Preparation.Utility.ActiveSkillType.SuperFast: | |||
| msg.MessageOfHuman.ActiveSkillType = Communication.Proto.ActiveSkillType.SuperFast; | |||
| break; | |||
| default: | |||
| msg.MessageOfHuman.ActiveSkillType = Communication.Proto.ActiveSkillType.NullActiveSkillType; | |||
| break; | |||
| } | |||
| switch (player.BulletOfPlayer) | |||
| { | |||
| case Preparation.Utility.BulletType.AtomBomb: | |||
| msg.MessageOfHuman.BulletType = Communication.Proto.BulletType.AtomBomb; | |||
| break; | |||
| case Preparation.Utility.BulletType.OrdinaryBullet: | |||
| msg.MessageOfHuman.BulletType = Communication.Proto.BulletType.OrdinaryBullet; | |||
| break; | |||
| case Preparation.Utility.BulletType.FastBullet: | |||
| msg.MessageOfHuman.BulletType = Communication.Proto.BulletType.FastBullet; | |||
| break; | |||
| case Preparation.Utility.BulletType.LineBullet: | |||
| msg.MessageOfHuman.BulletType = Communication.Proto.BulletType.LineBullet; | |||
| break; | |||
| default: | |||
| msg.MessageOfHuman.BulletType = Communication.Proto.BulletType.NullBulletType; | |||
| break; | |||
| }*/ | |||
| return msg; | |||
| } | |||
| /*private static MessageToClient.Types.GameObjMessage Bullet(Bullet bullet) | |||
| private static MessageOfObj Bullet(Bullet bullet) | |||
| { | |||
| MessageToClient.Types.GameObjMessage msg = new MessageToClient.Types.GameObjMessage(); | |||
| msg.MessageOfBullet = new MessageOfBullet(); | |||
| msg.MessageOfBullet.FacingDirection = bullet.FacingDirection; | |||
| msg.MessageOfBullet.Guid = bullet.ID; | |||
| msg.MessageOfBullet.BombRange = BulletFactory.BulletBombRange(bullet.TypeOfBullet); | |||
| MessageOfObj msg = new MessageOfObj(); | |||
| msg.BulletMessage = new(); | |||
| msg.BulletMessage.X = bullet.Position.x; | |||
| msg.BulletMessage.Y = bullet.Position.y; | |||
| //msg.BulletMessage.FacingDirection = bullet.FacingDirection; // XY转double? | |||
| msg.BulletMessage.Guid = bullet.ID; | |||
| msg.BulletMessage.Team = PlayerType.NullPlayerType; | |||
| msg.BulletMessage.Place = PlaceType.NullPlaceType; | |||
| msg.BulletMessage.BombRange = 0; | |||
| switch (bullet.TypeOfBullet) | |||
| { | |||
| case Preparation.Utility.BulletType.AtomBomb: | |||
| msg.MessageOfBullet.Type = Communication.Proto.BulletType.AtomBomb; | |||
| msg.BulletMessage.Type = BulletType.AtomBomb; | |||
| break; | |||
| case Preparation.Utility.BulletType.OrdinaryBullet: | |||
| msg.MessageOfBullet.Type = Communication.Proto.BulletType.OrdinaryBullet; | |||
| msg.BulletMessage.Type = BulletType.OrdinaryBullet; | |||
| break; | |||
| case Preparation.Utility.BulletType.FastBullet: | |||
| msg.MessageOfBullet.Type = Communication.Proto.BulletType.FastBullet; | |||
| msg.BulletMessage.Type = BulletType.FastBullet; | |||
| break; | |||
| case Preparation.Utility.BulletType.LineBullet: | |||
| msg.MessageOfBullet.Type = Communication.Proto.BulletType.LineBullet; | |||
| msg.BulletMessage.Type = BulletType.LineBullet; | |||
| break; | |||
| default: | |||
| msg.MessageOfBullet.Type = Communication.Proto.BulletType.NullBulletType; | |||
| msg.BulletMessage.Type = BulletType.NullBulletType; | |||
| break; | |||
| } | |||
| msg.MessageOfBullet.X = bullet.Position.x; | |||
| msg.MessageOfBullet.Y = bullet.Position.y; | |||
| if (bullet.Parent != null) | |||
| msg.MessageOfBullet.ParentTeamID = bullet.Parent.TeamID; | |||
| switch (bullet.Place) | |||
| //if (bullet.Parent != null) | |||
| //msg.BulletMessage.MessageOfBullet.ParentTeamID = bullet.Parent.TeamID; | |||
| /*switch (bullet.Place) | |||
| { | |||
| case Preparation.Utility.PlaceType.Null: | |||
| msg.MessageOfBullet.Place = Communication.Proto.PlaceType.Null; | |||
| msg.BulletMessage.MessageOfBullet.Place = Communication.Proto.PlaceType.Null; | |||
| break; | |||
| case Preparation.Utility.PlaceType.Grass: | |||
| msg.MessageOfBullet.Place = Communication.Proto.PlaceType.Grass; | |||
| msg.BulletMessage.MessageOfBullet.Place = Communication.Proto.PlaceType.Grass; | |||
| break; | |||
| case Preparation.Utility.PlaceType.Grass: | |||
| msg.MessageOfBullet.Place = Communication.Proto.PlaceType.Grass; | |||
| msg.BulletMessage.MessageOfBullet.Place = Communication.Proto.PlaceType.Grass; | |||
| break; | |||
| case Preparation.Utility.PlaceType.Grass: | |||
| msg.MessageOfBullet.Place = Communication.Proto.PlaceType.Grass; | |||
| msg.BulletMessage.MessageOfBullet.Place = Communication.Proto.PlaceType.Grass; | |||
| break; | |||
| default: | |||
| msg.MessageOfBullet.Place = Communication.Proto.PlacccceType.NullPlaceType; | |||
| msg.BulletMessage.MessageOfBullet.Place = Communication.Proto.PlacccceType.NullPlaceType; | |||
| break; | |||
| } | |||
| }*/ | |||
| return msg; | |||
| }*/ | |||
| } | |||
| private static MessageOfProp Prop(Prop prop) | |||
| private static MessageOfObj Prop(Prop prop) | |||
| { | |||
| MessageOfProp msg = new MessageOfProp(); | |||
| //msg.Type = PropType.NullPropType; 下面写 | |||
| msg.X = prop.Position.x; | |||
| msg.Y = prop.Position.y; | |||
| msg.FacingDirection = 0; | |||
| msg.Guid = 0; | |||
| msg.Place = PlaceType.NullPlaceType; | |||
| msg.Size = 0; | |||
| msg.IsMoving = false; | |||
| /* THUAI5中的内容 | |||
| msg.MessageOfProp.FacingDirection = prop.FacingDirection; | |||
| msg.MessageOfProp.Guid = prop.ID; | |||
| msg.MessageOfProp.IsMoving = prop.IsMoving;*/ | |||
| MessageOfObj msg = new MessageOfObj(); | |||
| msg.PropMessage = new(); | |||
| //msg.PropMessage.Type = PropType.NullPropType; 下面写 | |||
| msg.PropMessage.X = prop.Position.x; | |||
| msg.PropMessage.Y = prop.Position.y; | |||
| msg.PropMessage.FacingDirection = 0; | |||
| msg.PropMessage.Guid = 0; | |||
| msg.PropMessage.Place = PlaceType.NullPlaceType; | |||
| msg.PropMessage.Size = 0; | |||
| msg.PropMessage.IsMoving = false; | |||
| switch (prop.GetPropType()) | |||
| { | |||
| /*case Preparation.Utility.PropType.Gem: | |||
| msg.Type = PropType.Gem; | |||
| msg.PropMessage.Type = PropType.Gem; | |||
| break; | |||
| case Preparation.Utility.PropType.addLIFE: | |||
| msg.Type = PropType.AddLife; | |||
| msg.PropMessage.Type = PropType.AddLife; | |||
| break; | |||
| case Preparation.Utility.PropType.addSpeed: | |||
| msg.Type = PropType.AddSpeed; | |||
| msg.PropMessage.Type = PropType.AddSpeed; | |||
| break; | |||
| case Preparation.Utility.PropType.Shield: | |||
| msg.Type = PropType.Shield; | |||
| msg.PropMessage.Type = PropType.Shield; | |||
| break; | |||
| case Preparation.Utility.PropType.Spear: | |||
| msg.Type = PropType.Spear; | |||
| msg.PropMessage.Type = PropType.Spear; | |||
| break;*/ | |||
| default: | |||
| msg.Type = PropType.NullPropType; | |||
| msg.PropMessage.Type = PropType.NullPropType; | |||
| break; | |||
| } | |||
| /*if(prop is Gem) | |||
| { | |||
| msg.MessageOfProp.Size = ((Gem)prop).Size; | |||
| msg.PropMessage.MessageOfProp.Size = ((Gem)prop).Size; | |||
| } | |||
| else | |||
| { | |||
| msg.MessageOfProp.Size = 1; | |||
| msg.PropMessage.MessageOfProp.Size = 1; | |||
| } | |||
| switch (prop.Place) | |||
| { | |||
| case Preparation.Utility.PlaceType.Null: | |||
| msg.MessageOfProp.Place = Communication.Proto.PlaceType.Null; | |||
| msg.PropMessage.MessageOfProp.Place = Communication.Proto.PlaceType.Null; | |||
| break; | |||
| case Preparation.Utility.PlaceType.Grass: | |||
| msg.MessageOfProp.Place = Communication.Proto.PlaceType.Grass; | |||
| msg.PropMessage.MessageOfProp.Place = Communication.Proto.PlaceType.Grass; | |||
| break; | |||
| case Preparation.Utility.PlaceType.Grass: | |||
| msg.MessageOfProp.Place = Communication.Proto.PlaceType.Grass; | |||
| msg.PropMessage.MessageOfProp.Place = Communication.Proto.PlaceType.Grass; | |||
| break; | |||
| case Preparation.Utility.PlaceType.Grass: | |||
| msg.MessageOfProp.Place = Communication.Proto.PlaceType.Grass; | |||
| msg.PropMessage.MessageOfProp.Place = Communication.Proto.PlaceType.Grass; | |||
| break; | |||
| default: | |||
| msg.MessageOfProp.Place = Communication.Proto.PlacccceType.NullPlaceType; | |||
| msg.PropMessage.MessageOfProp.Place = Communication.Proto.PlacccceType.NullPlaceType; | |||
| break; | |||
| }*/ | |||
| return msg; | |||
| } | |||
| /*private static MessageOfBombedBullet BombedBullet(BombedBullet bombedBullet) | |||
| private static MessageOfObj BombedBullet(BombedBullet bombedBullet) | |||
| { | |||
| MessageOfBombedBullet msg = new MessageOfBombedBullet; | |||
| msg.FacingDirection = bombedBullet.FacingDirection; | |||
| msg.X = bombedBullet.bulletHasBombed.Position.x; | |||
| msg.Y = bombedBullet.bulletHasBombed.Position.y; | |||
| msg.MappingID = bombedBullet.MappingID; | |||
| msg.BombRange = BulletFactory.BulletBombRange(bombedBullet.bulletHasBombed.TypeOfBullet); | |||
| MessageOfObj msg = new MessageOfObj(); | |||
| msg.BombedBulletMessage = new(); | |||
| msg.BombedBulletMessage.X = bombedBullet.bulletHasBombed.Position.x; | |||
| msg.BombedBulletMessage.Y = bombedBullet.bulletHasBombed.Position.y; | |||
| //msg.BombedBulletMessage.FacingDirection = bombedBullet.FacingDirection; XY类型转double? | |||
| msg.BombedBulletMessage.MappingId = bombedBullet.MappingID; | |||
| msg.BombedBulletMessage.BombRange = BulletFactory.BulletRadius(bombedBullet.bulletHasBombed.TypeOfBullet); // 待确认 | |||
| switch (bombedBullet.bulletHasBombed.TypeOfBullet) | |||
| { | |||
| case Preparation.Utility.BulletType.OrdinaryBullet: | |||
| msg.MessageOfBombedBullet.Type = Communication.Proto.BulletType.OrdinaryBullet; | |||
| msg.BombedBulletMessage.Type = BulletType.OrdinaryBullet; | |||
| break; | |||
| case Preparation.Utility.BulletType.AtomBomb: | |||
| msg.MessageOfBombedBullet.Type = Communication.Proto.BulletType.AtomBomb; | |||
| msg.BombedBulletMessage.Type = BulletType.AtomBomb; | |||
| break; | |||
| case Preparation.Utility.BulletType.FastBullet: | |||
| msg.MessageOfBombedBullet.Type = Communication.Proto.BulletType.FastBullet; | |||
| msg.BombedBulletMessage.Type = BulletType.FastBullet; | |||
| break; | |||
| case Preparation.Utility.BulletType.LineBullet: | |||
| msg.MessageOfBombedBullet.Type = Communication.Proto.BulletType.LineBullet; | |||
| msg.BombedBulletMessage.Type = BulletType.LineBullet; | |||
| break; | |||
| default: | |||
| msg.MessageOfBombedBullet.Type = Communication.Proto.BulletType.NullBulletType; | |||
| msg.BombedBulletMessage.Type = BulletType.NullBulletType; | |||
| break; | |||
| } | |||
| return msg; | |||
| }*/ | |||
| } | |||
| /*private static MessageToClient.Types.GameObjMessage PickedProp(PickedProp pickedProp) | |||
| private static MessageOfObj PickedProp(PickedProp pickedProp) | |||
| { | |||
| MessageToClient.Types.GameObjMessage msg = new MessageToClient.Types.GameObjMessage(); | |||
| msg.MessageOfPickedProp = new MessageOfPickedProp(); | |||
| MessageOfObj msg = new MessageOfObj(); // MessageOfObj中没有PickedProp | |||
| /*msg.MessageOfPickedProp = new MessageOfPickedProp(); | |||
| msg.MessageOfPickedProp.MappingID = pickedProp.MappingID; | |||
| msg.MessageOfPickedProp.X = pickedProp.PropHasPicked.Position.x; | |||
| @@ -534,8 +386,8 @@ namespace Server | |||
| default: | |||
| msg.MessageOfPickedProp.Type = Communication.Proto.PropType.NullPropType; | |||
| break; | |||
| } | |||
| }*/ | |||
| return msg; | |||
| }*/ | |||
| } | |||
| } | |||
| } | |||
| @@ -7,6 +7,7 @@ using System.Net.Http.Headers; | |||
| using Gaming; | |||
| using GameClass.GameObj; | |||
| using Preparation.Utility; | |||
| using Playback; | |||
| namespace Server | |||
| @@ -31,13 +32,13 @@ namespace Server | |||
| protected readonly ArgumentOptions options; | |||
| protected readonly Game game; | |||
| private uint spectatorMinPlayerID = 2022; | |||
| private List<Tuple<PlayerType, uint>> spectatorList = new List<Tuple<PlayerType, uint>>(); | |||
| private List<uint> spectatorList = new List<uint>(); | |||
| public int TeamCount => options.TeamCount; | |||
| protected long[,] communicationToGameID; // 通信用的ID映射到游戏内的ID,[i,j]表示team:i,player:j的id。 | |||
| private readonly object messageToAllClientsLock = new(); | |||
| public static readonly long SendMessageToClientIntervalInMilliseconds = 50; | |||
| private readonly Semaphore endGameInfoSema = new(0, 1); | |||
| // private MessageWriter? mwr = null; | |||
| private MessageWriter? mwr = null; | |||
| public SemaphoreSlim StartGameTest() | |||
| { | |||
| @@ -81,40 +82,75 @@ namespace Server | |||
| } | |||
| public void StartGame() | |||
| { | |||
| bool gameState = game.StartGame((int)options.GameTimeInSecond * 1000); | |||
| var waitHandle = new SemaphoreSlim(gameState == true ? 1 : 0); // 注意修改 | |||
| game.StartGame((int)options.GameTimeInSecond * 1000); | |||
| Thread.Sleep(1); | |||
| new Thread(() => | |||
| { | |||
| bool flag = true; | |||
| new FrameRateTaskExecutor<int> | |||
| ( | |||
| () => game.GameMap.Timer.IsGaming, | |||
| ReportGame, | |||
| 1000, | |||
| () => | |||
| { | |||
| ReportGame(); // 最后发一次消息,唤醒发消息的线程,防止发消息的线程由于有概率处在 Wait 状态而卡住 | |||
| if (flag == true) | |||
| { | |||
| ReportGame(GameState.GameStart); | |||
| flag = false; | |||
| } | |||
| else ReportGame(GameState.GameRunning); | |||
| }, | |||
| SendMessageToClientIntervalInMilliseconds, | |||
| () => | |||
| { | |||
| ReportGame(GameState.GameEnd); // 最后发一次消息,唤醒发消息的线程,防止发消息的线程由于有概率处在 Wait 状态而卡住 | |||
| OnGameEnd(); | |||
| return 0; | |||
| } | |||
| ).Start(); | |||
| }) | |||
| { IsBackground = true }.Start(); | |||
| new Thread(() => | |||
| { | |||
| waitHandle.Wait(); | |||
| this.endGameSem.Release(); | |||
| }) | |||
| { IsBackground = true }.Start(); | |||
| } | |||
| public void WaitForEnd() | |||
| { | |||
| this.endGameSem.Wait(); | |||
| mwr?.Dispose(); | |||
| } | |||
| private void OnGameEnd() | |||
| { | |||
| game.ClearAllLists(); | |||
| mwr?.Flush(); | |||
| //if (options.ResultFileName != DefaultArgumentOptions.FileName) | |||
| //SaveGameResult(options.ResultFileName + ".json"); | |||
| //SendGameResult(); | |||
| endGameInfoSema.Release(); | |||
| } | |||
| public void ReportGame() | |||
| public void ReportGame(GameState gameState, bool requiredGaming = true) | |||
| { | |||
| //currentGameInfo = null; | |||
| var gameObjList = game.GetGameObj(); | |||
| currentGameInfo = new(); | |||
| lock (messageToAllClientsLock) | |||
| { | |||
| //currentGameInfo.MapMessage = (Messa(game.GameMap)); | |||
| if (gameState == GameState.GameStart) currentGameInfo.MapMessage = MapMsg(game.GameMap.ProtoGameMap); | |||
| switch (gameState) | |||
| { | |||
| case GameState.GameRunning: | |||
| case GameState.GameStart: | |||
| case GameState.GameEnd: | |||
| foreach (GameObj gameObj in gameObjList) | |||
| { | |||
| currentGameInfo.ObjMessage.Add(CopyInfo.Auto(gameObj)); | |||
| } | |||
| currentGameInfo.GameState = gameState; | |||
| currentGameInfo.AllMessage = new(); // 还没写 | |||
| mwr?.WriteOne(currentGameInfo); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| foreach (var kvp in semaDict) | |||
| { | |||
| @@ -127,25 +163,52 @@ namespace Server | |||
| } | |||
| } | |||
| private int PlayerTypeToTeamID(PlayerType playerType) | |||
| private int PlayerIDToTeamID(long playerID) | |||
| { | |||
| if (playerType == PlayerType.StudentPlayer) return 0; | |||
| if (playerType == PlayerType.TrickerPlayer) return 1; | |||
| if (0 <= playerID && playerID < options.PlayerCountPerTeam) return 0; | |||
| if (playerID == options.PlayerCountPerTeam) return 1; | |||
| return -1; | |||
| } | |||
| private uint GetBirthPointIdx(PlayerType playerType, long playerID) // 获取出生点位置 | |||
| private uint GetBirthPointIdx(long playerID) // 获取出生点位置 | |||
| { | |||
| return (uint)((PlayerTypeToTeamID(playerType) * options.PlayerCountPerTeam) + playerID + 1); | |||
| return (uint)(playerID + 1); | |||
| } | |||
| private bool ValidPlayerTypeAndPlayerID(PlayerType playerType, long playerID) | |||
| private bool ValidPlayerID(long playerID) | |||
| { | |||
| if (playerType == PlayerType.StudentPlayer && 0 <= playerID && playerID < options.PlayerCountPerTeam) | |||
| return true; // 人数待修改 | |||
| if (playerType == PlayerType.TrickerPlayer && 0 <= playerID && playerID < options.PlayerCountPerTeam) | |||
| if (0 <= playerID && playerID < options.PlayerCountPerTeam + 1) | |||
| return true; | |||
| return false; | |||
| } | |||
| private Protobuf.PlaceType IntToPlaceType(uint n) | |||
| { | |||
| switch (n) | |||
| { | |||
| case 0: return Protobuf.PlaceType.Land; | |||
| case 6: return Protobuf.PlaceType.Wall; | |||
| case 7: return Protobuf.PlaceType.Grass; | |||
| case 8: return Protobuf.PlaceType.Classroom; | |||
| case 9: return Protobuf.PlaceType.Gate; | |||
| case 10: return Protobuf.PlaceType.HiddenGate; | |||
| case 11: return Protobuf.PlaceType.Window; | |||
| case 12: return Protobuf.PlaceType.Door; | |||
| case 13: return Protobuf.PlaceType.Chest; | |||
| default: return Protobuf.PlaceType.NullPlaceType; | |||
| } | |||
| } | |||
| private MessageOfMap MapMsg(uint[,] map) | |||
| { | |||
| MessageOfMap msgOfMap = new MessageOfMap(); | |||
| for (int i = 0; i < GameData.rows; i++) | |||
| { | |||
| msgOfMap.Row.Add(new MessageOfMap.Types.Row()); | |||
| for (int j = 0; j < GameData.cols; j++) | |||
| { | |||
| msgOfMap.Row[i].Col.Add(IntToPlaceType(map[i, j])); | |||
| } | |||
| } | |||
| return msgOfMap; | |||
| } | |||
| public override Task<BoolRes> TryConnection(IDMsg request, ServerCallContext context) | |||
| { | |||
| Console.WriteLine($"TryConnection ID: {request.PlayerId}"); | |||
| @@ -167,10 +230,10 @@ namespace Server | |||
| public override async Task AddPlayer(PlayerMsg request, IServerStreamWriter<MessageToClient> responseStream, ServerCallContext context) | |||
| { | |||
| Console.WriteLine($"AddPlayer: {request.PlayerId}"); | |||
| if (request.PlayerId >= spectatorMinPlayerID && request.PlayerType == PlayerType.NullPlayerType) | |||
| if (request.PlayerId >= spectatorMinPlayerID) | |||
| { | |||
| // 观战模式 | |||
| Tuple<PlayerType, uint> tp = new Tuple<PlayerType, uint>(request.PlayerType, (uint)request.PlayerId); | |||
| uint tp = (uint)request.PlayerId; | |||
| if (!spectatorList.Contains(tp)) | |||
| { | |||
| spectatorList.Add(tp); | |||
| @@ -181,7 +244,7 @@ namespace Server | |||
| if (game.GameMap.Timer.IsGaming) | |||
| return; | |||
| if (!ValidPlayerTypeAndPlayerID(request.PlayerType, request.PlayerId)) //玩家id是否正确 | |||
| if (!ValidPlayerID(request.PlayerId)) //玩家id是否正确 | |||
| return; | |||
| //if (communicationToGameID[PlayerTypeToTeamID(request.PlayerType), request.PlayerId] != GameObj.invalidID) //是否已经添加了该玩家 | |||
| //return; | |||
| @@ -190,15 +253,15 @@ namespace Server | |||
| lock (addPlayerLock) | |||
| { | |||
| Game.PlayerInitInfo playerInitInfo = new(GetBirthPointIdx(request.PlayerType, request.PlayerId), PlayerTypeToTeamID(request.PlayerType), request.PlayerId, characterType); | |||
| Game.PlayerInitInfo playerInitInfo = new(GetBirthPointIdx(request.PlayerId), PlayerIDToTeamID(request.PlayerId), request.PlayerId, characterType); | |||
| long newPlayerID = game.AddPlayer(playerInitInfo); | |||
| if (newPlayerID == GameObj.invalidID) | |||
| return; | |||
| communicationToGameID[PlayerTypeToTeamID(request.PlayerType), request.PlayerId] = newPlayerID; | |||
| communicationToGameID[PlayerIDToTeamID(request.PlayerId), request.PlayerId] = newPlayerID; | |||
| // 内容待修改 | |||
| var temp = (new SemaphoreSlim(0, 1), new SemaphoreSlim(0, 1)); | |||
| bool start = false; | |||
| Console.WriteLine($"PlayerType: {request.PlayerType} Id: {request.PlayerId} joins."); | |||
| Console.WriteLine($"Id: {request.PlayerId} joins."); | |||
| lock (semaDict) | |||
| { | |||
| semaDict.Add(request.PlayerId, temp); | |||
| @@ -218,13 +281,13 @@ namespace Server | |||
| if (currentGameInfo != null) | |||
| { | |||
| await responseStream.WriteAsync(currentGameInfo); | |||
| Console.WriteLine("Send!"); | |||
| //Console.WriteLine("Send!"); | |||
| } | |||
| semaDict[request.PlayerId].Item2.Release(); | |||
| } while (game.GameMap.Timer.IsGaming); | |||
| } | |||
| public override Task<BoolRes> Trick(TrickMsg request, ServerCallContext context) | |||
| public override Task<BoolRes> Attack(AttackMsg request, ServerCallContext context) | |||
| { | |||
| game.Attack(request.PlayerId, request.Angle); | |||
| BoolRes boolRes = new(); | |||
| @@ -239,8 +302,10 @@ namespace Server | |||
| public override Task<MoveRes> Move(MoveMsg request, ServerCallContext context) | |||
| { | |||
| Console.WriteLine($"SetPos ID: {request.PlayerId}, TimeInMilliseconds: {request.TimeInMilliseconds}"); | |||
| var gameID = communicationToGameID[PlayerTypeToTeamID(request.PlayerType), request.PlayerId]; | |||
| #if DEBUG | |||
| Console.WriteLine($"Move ID: {request.PlayerId}, TimeInMilliseconds: {request.TimeInMilliseconds}"); | |||
| #endif | |||
| var gameID = communicationToGameID[PlayerIDToTeamID(request.PlayerId), request.PlayerId]; | |||
| game.MovePlayer(gameID, (int)request.TimeInMilliseconds, request.Angle); | |||
| // 之后game.MovePlayer可能改为bool类型 | |||
| MoveRes moveRes = new(); | |||
| @@ -283,7 +348,12 @@ namespace Server | |||
| } | |||
| public override Task<BoolRes> StartLearning(IDMsg request, ServerCallContext context) | |||
| { | |||
| return base.StartLearning(request, context); | |||
| #if DEBUG | |||
| Console.WriteLine($"StartLearning ID: {request.PlayerId}"); | |||
| #endif | |||
| BoolRes boolRes = new(); | |||
| boolRes.ActSuccess = game.Fix(request.PlayerId); | |||
| return Task.FromResult(boolRes); | |||
| } | |||
| public GameServer(ArgumentOptions options) | |||
| @@ -348,7 +418,7 @@ namespace Server | |||
| { | |||
| try | |||
| { | |||
| //mwr = new MessageWriter(options.FileName, options.TeamCount, options.PlayerCountPerTeam); | |||
| mwr = new MessageWriter(options.FileName, options.TeamCount, options.PlayerCountPerTeam); | |||
| } | |||
| catch | |||
| { | |||
| @@ -34,7 +34,7 @@ namespace Server | |||
| Grpc.Core.Server server = new Grpc.Core.Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) | |||
| { | |||
| Services = { AvailableService.BindService(gameServer) }, | |||
| Ports = { new ServerPort("127.0.0.1", 8888, ServerCredentials.Insecure) } | |||
| Ports = { new ServerPort("0.0.0.0", 8888, ServerCredentials.Insecure) } | |||
| }; | |||
| server.Start(); | |||
| @@ -21,6 +21,7 @@ | |||
| <ItemGroup> | |||
| <ProjectReference Include="..\..\dependency\proto\Protos.csproj" /> | |||
| <ProjectReference Include="..\..\playback\Playback\Playback.csproj" /> | |||
| <ProjectReference Include="..\GameClass\GameClass.csproj" /> | |||
| <ProjectReference Include="..\GameEngine\GameEngine.csproj" /> | |||
| <ProjectReference Include="..\Gaming\Gaming.csproj" /> | |||
| @@ -17,6 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Protos", "..\dependency\pro | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameEngine", "GameEngine\GameEngine.csproj", "{1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}" | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Playback", "..\playback\Playback\Playback.csproj", "{FF22960A-6BD9-4C80-A029-9A39FB8F64C4}" | |||
| EndProject | |||
| Global | |||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
| Debug|Any CPU = Debug|Any CPU | |||
| @@ -51,6 +53,10 @@ Global | |||
| {1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {FF22960A-6BD9-4C80-A029-9A39FB8F64C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {FF22960A-6BD9-4C80-A029-9A39FB8F64C4}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {FF22960A-6BD9-4C80-A029-9A39FB8F64C4}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {FF22960A-6BD9-4C80-A029-9A39FB8F64C4}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| EndGlobalSection | |||
| GlobalSection(SolutionProperties) = preSolution | |||
| HideSolutionNode = FALSE | |||
| @@ -1,5 +1,5 @@ | |||
| using Communication.Proto; | |||
| using Google.Protobuf; | |||
| using Google.Protobuf; | |||
| using Protobuf; | |||
| using System; | |||
| using System.IO; | |||
| using System.IO.Compression; | |||
| @@ -1,5 +1,5 @@ | |||
| using Communication.Proto; | |||
| using Google.Protobuf; | |||
| using Protobuf; | |||
| using System; | |||
| using System.IO; | |||
| using System.IO.Compression; | |||
| @@ -1,9 +1,17 @@ | |||
| <Project Sdk="Microsoft.NET.Sdk"> | |||
| <Project Sdk="Microsoft.NET.Sdk"> | |||
| <PropertyGroup> | |||
| <TargetFrameworks>net6.0;netstandard2.1</TargetFrameworks> | |||
| <TargetFrameworks>net6.0</TargetFrameworks> | |||
| <ImplicitUsings>enable</ImplicitUsings> | |||
| <Nullable>enable</Nullable> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="Google.Protobuf" Version="3.22.1" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <ProjectReference Include="..\..\dependency\proto\Protos.csproj" /> | |||
| </ItemGroup> | |||
| </Project> | |||