| @@ -0,0 +1,3 @@ | |||
| # These are supported funding model platforms | |||
| github: [TCL606] | |||
| @@ -1,13 +0,0 @@ | |||
| name: clang-format | |||
| on: [push, pull_request] | |||
| jobs: | |||
| clang-format-checking: | |||
| runs-on: ubuntu-latest | |||
| steps: | |||
| - uses: actions/checkout@v3 | |||
| - uses: DoozyX/clang-format-lint-action@v0.14 | |||
| with: | |||
| source: '.' | |||
| extensions: 'cs,c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx,i,ixx,ipp,i++' | |||
| clangFormatVersion: 14 | |||
| inplace: False | |||
| @@ -0,0 +1,34 @@ | |||
| name: format | |||
| on: [push, pull_request] | |||
| jobs: | |||
| clang-format-checking: | |||
| runs-on: ubuntu-latest | |||
| steps: | |||
| - uses: actions/checkout@v3 | |||
| - uses: DoozyX/clang-format-lint-action@v0.14 | |||
| with: | |||
| source: '.' | |||
| extensions: 'c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx,i,ixx,ipp,i++' | |||
| clangFormatVersion: 14 | |||
| inplace: False | |||
| dotnet-format-checking: | |||
| runs-on: ubuntu-latest | |||
| steps: | |||
| - uses: actions/checkout@v3 | |||
| - name: Setup .NET Core | |||
| uses: actions/setup-dotnet@v3 | |||
| with: | |||
| dotnet-version: 6.0.x | |||
| - name: Check Logic | |||
| run: dotnet format "./logic/logic.sln" --severity error --no-restore | |||
| - name: Check Installer | |||
| run: dotnet format "./installer/installer.sln" --severity error --no-restore | |||
| - name: Check Launcher | |||
| run: dotnet format "./launcher/launcher.sln" --severity error --no-restore | |||
| - name: Check Playback | |||
| run: dotnet format "./playback/playback.sln" --severity error --no-restore | |||
| @@ -45,25 +45,24 @@ public: | |||
| virtual bool HaveMessage() = 0; | |||
| virtual std::pair<int64_t, std::string> GetMessage() = 0; | |||
| virtual bool WaitThread() = 0; | |||
| virtual int GetCounter() const = 0; | |||
| // IHumanAPI使用的部分 | |||
| virtual bool Escape() = 0; | |||
| // 说明:双向stream由三个函数共同实现,两个记录开始和结束,结果由Logic里的私有的成员变量记录,获得返回值则另调函数 | |||
| virtual void StartFixMachine() = 0; | |||
| virtual void EndFixMachine() = 0; | |||
| virtual bool GetFixStatus() = 0; | |||
| virtual bool StartFixMachine() = 0; | |||
| virtual bool EndFixMachine() = 0; | |||
| virtual void StartSaveHuman() = 0; | |||
| virtual void EndSaveHuman() = 0; | |||
| virtual bool GetSaveStatus() = 0; | |||
| virtual bool StartSaveHuman() = 0; | |||
| virtual bool EndSaveHuman() = 0; | |||
| // IButcherAPI使用的部分 | |||
| virtual bool Attack(double angle) = 0; | |||
| virtual bool CarryHuman() = 0; | |||
| virtual bool ReleaseHuman() = 0; | |||
| virtual bool HangHuman() = 0; | |||
| virtual bool WaitThread() = 0; | |||
| virtual int GetCounter() = 0; | |||
| }; | |||
| class IAPI | |||
| @@ -129,12 +128,10 @@ class IHumanAPI : public IAPI | |||
| public: | |||
| /*****人类阵营的特定函数*****/ | |||
| virtual void StartFixMachine() = 0; | |||
| virtual void EndFixMachine() = 0; | |||
| virtual std::future<bool> GetFixStatus() = 0; | |||
| virtual void StartSaveHuman() = 0; | |||
| virtual void EndSaveHuman() = 0; | |||
| virtual std::future<bool> GetSaveStatus() = 0; | |||
| virtual std::future<bool> StartFixMachine() = 0; | |||
| virtual std::future<bool> EndFixMachine() = 0; | |||
| virtual std::future<bool> StartSaveHuman() = 0; | |||
| virtual std::future<bool> EndSaveHuman() = 0; | |||
| virtual std::future<bool> Escape() = 0; | |||
| [[nodiscard]] virtual std::shared_ptr<const THUAI6::Human> GetSelfInfo() const = 0; | |||
| }; | |||
| @@ -205,16 +202,12 @@ public: | |||
| [[nodiscard]] std::vector<std::vector<THUAI6::PlaceType>> GetFullMap() const override; | |||
| [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t CellX, int32_t CellY) const override; | |||
| [[nodiscard]] const std::vector<int64_t> GetPlayerGUIDs() const override | |||
| { | |||
| } | |||
| [[nodiscard]] const std::vector<int64_t> GetPlayerGUIDs() const override; | |||
| void StartFixMachine() override; | |||
| void EndFixMachine() override; | |||
| std::future<bool> GetFixStatus() override; | |||
| void StartSaveHuman() override; | |||
| void EndSaveHuman() override; | |||
| std::future<bool> GetSaveStatus() override; | |||
| std::future<bool> StartFixMachine() override; | |||
| std::future<bool> EndFixMachine() override; | |||
| std::future<bool> StartSaveHuman() override; | |||
| std::future<bool> EndSaveHuman() override; | |||
| std::future<bool> Escape() override; | |||
| [[nodiscard]] std::shared_ptr<const THUAI6::Human> GetSelfInfo() const override; | |||
| @@ -268,9 +261,7 @@ public: | |||
| [[nodiscard]] std::vector<std::vector<THUAI6::PlaceType>> GetFullMap() const override; | |||
| [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t CellX, int32_t CellY) const override; | |||
| [[nodiscard]] const std::vector<int64_t> GetPlayerGUIDs() const override | |||
| { | |||
| } | |||
| [[nodiscard]] const std::vector<int64_t> GetPlayerGUIDs() const override; | |||
| std::future<bool> Attack(double angleInRadian) override; | |||
| std::future<bool> CarryHuman() override; | |||
| @@ -297,97 +288,45 @@ public: | |||
| } | |||
| void Play(IAI& ai) override; | |||
| std::future<bool> Move(int64_t timeInMilliseconds, double angleInRadian) override | |||
| { | |||
| } | |||
| std::future<bool> Move(int64_t timeInMilliseconds, double angleInRadian) override; | |||
| [[nodiscard]] int GetFrameCount() const override | |||
| { | |||
| } | |||
| std::future<bool> MoveRight(int64_t timeInMilliseconds) override | |||
| { | |||
| } | |||
| std::future<bool> MoveUp(int64_t timeInMilliseconds) override | |||
| { | |||
| } | |||
| std::future<bool> MoveLeft(int64_t timeInMilliseconds) override | |||
| { | |||
| } | |||
| std::future<bool> MoveDown(int64_t timeInMilliseconds) override | |||
| { | |||
| } | |||
| std::future<bool> MoveRight(int64_t timeInMilliseconds) override; | |||
| std::future<bool> MoveUp(int64_t timeInMilliseconds) override; | |||
| std::future<bool> MoveLeft(int64_t timeInMilliseconds) override; | |||
| std::future<bool> MoveDown(int64_t timeInMilliseconds) override; | |||
| std::future<bool> PickProp(THUAI6::PropType prop) override | |||
| { | |||
| } | |||
| std::future<bool> UseProp() override | |||
| { | |||
| } | |||
| std::future<bool> UseSkill() override | |||
| { | |||
| } | |||
| std::future<bool> PickProp(THUAI6::PropType prop) override; | |||
| std::future<bool> UseProp() override; | |||
| std::future<bool> UseSkill() override; | |||
| std::future<bool> SendMessage(int64_t, std::string) override | |||
| { | |||
| } | |||
| [[nodiscard]] std::future<bool> HaveMessage() override | |||
| { | |||
| } | |||
| [[nodiscard]] std::future<std::pair<int64_t, std::string>> GetMessage() override | |||
| { | |||
| } | |||
| std::future<bool> SendMessage(int64_t, std::string) override; | |||
| [[nodiscard]] std::future<bool> HaveMessage() override; | |||
| [[nodiscard]] std::future<std::pair<int64_t, std::string>> GetMessage() override; | |||
| std::future<bool> Wait() override | |||
| { | |||
| } | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Human>> GetHuman() const override | |||
| { | |||
| } | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Butcher>> GetButcher() const override | |||
| { | |||
| } | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Human>> GetHuman() const override; | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Butcher>> GetButcher() const override; | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Prop>> GetProps() const override | |||
| { | |||
| } | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Prop>> GetProps() const override; | |||
| [[nodiscard]] std::vector<std::vector<THUAI6::PlaceType>> GetFullMap() const override | |||
| { | |||
| } | |||
| [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t CellX, int32_t CellY) const override | |||
| { | |||
| } | |||
| [[nodiscard]] std::vector<std::vector<THUAI6::PlaceType>> GetFullMap() const override; | |||
| [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t CellX, int32_t CellY) const override; | |||
| [[nodiscard]] const std::vector<int64_t> GetPlayerGUIDs() const override | |||
| { | |||
| } | |||
| [[nodiscard]] const std::vector<int64_t> GetPlayerGUIDs() const override; | |||
| void StartFixMachine() override | |||
| { | |||
| } | |||
| void EndFixMachine() override | |||
| { | |||
| } | |||
| std::future<bool> GetFixStatus() override | |||
| { | |||
| } | |||
| void StartSaveHuman() override | |||
| { | |||
| } | |||
| void EndSaveHuman() override | |||
| { | |||
| } | |||
| std::future<bool> GetSaveStatus() override | |||
| { | |||
| } | |||
| std::future<bool> Escape() override | |||
| { | |||
| } | |||
| [[nodiscard]] virtual std::shared_ptr<const THUAI6::Human> GetSelfInfo() const override | |||
| { | |||
| } | |||
| std::future<bool> StartFixMachine() override; | |||
| std::future<bool> EndFixMachine() override; | |||
| std::future<bool> StartSaveHuman() override; | |||
| std::future<bool> EndSaveHuman() override; | |||
| std::future<bool> Escape() override; | |||
| [[nodiscard]] virtual std::shared_ptr<const THUAI6::Human> GetSelfInfo() const override; | |||
| private: | |||
| ILogic& logic; | |||
| @@ -408,88 +347,44 @@ public: | |||
| } | |||
| void Play(IAI& ai) override; | |||
| std::future<bool> Move(int64_t timeInMilliseconds, double angleInRadian) override | |||
| { | |||
| } | |||
| std::future<bool> Move(int64_t timeInMilliseconds, double angleInRadian) override; | |||
| [[nodiscard]] int GetFrameCount() const override | |||
| { | |||
| } | |||
| std::future<bool> MoveRight(int64_t timeInMilliseconds) override | |||
| { | |||
| } | |||
| std::future<bool> MoveUp(int64_t timeInMilliseconds) override | |||
| { | |||
| } | |||
| std::future<bool> MoveLeft(int64_t timeInMilliseconds) override | |||
| { | |||
| } | |||
| std::future<bool> MoveDown(int64_t timeInMilliseconds) override | |||
| { | |||
| } | |||
| std::future<bool> MoveRight(int64_t timeInMilliseconds) override; | |||
| std::future<bool> MoveUp(int64_t timeInMilliseconds) override; | |||
| std::future<bool> MoveLeft(int64_t timeInMilliseconds) override; | |||
| std::future<bool> MoveDown(int64_t timeInMilliseconds) override; | |||
| std::future<bool> PickProp(THUAI6::PropType prop) override | |||
| { | |||
| } | |||
| std::future<bool> UseProp() override | |||
| { | |||
| } | |||
| std::future<bool> UseSkill() override | |||
| { | |||
| } | |||
| std::future<bool> PickProp(THUAI6::PropType prop) override; | |||
| std::future<bool> UseProp() override; | |||
| std::future<bool> UseSkill() override; | |||
| std::future<bool> SendMessage(int64_t, std::string) override | |||
| { | |||
| } | |||
| [[nodiscard]] std::future<bool> HaveMessage() override | |||
| { | |||
| } | |||
| [[nodiscard]] std::future<std::pair<int64_t, std::string>> GetMessage() override | |||
| { | |||
| } | |||
| std::future<bool> SendMessage(int64_t, std::string) override; | |||
| [[nodiscard]] std::future<bool> HaveMessage() override; | |||
| [[nodiscard]] std::future<std::pair<int64_t, std::string>> GetMessage() override; | |||
| std::future<bool> Wait() override | |||
| { | |||
| } | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Human>> GetHuman() const override | |||
| { | |||
| } | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Butcher>> GetButcher() const override | |||
| { | |||
| } | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Human>> GetHuman() const override; | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Butcher>> GetButcher() const override; | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Prop>> GetProps() const override | |||
| { | |||
| } | |||
| [[nodiscard]] std::vector<std::shared_ptr<const THUAI6::Prop>> GetProps() const override; | |||
| [[nodiscard]] std::vector<std::vector<THUAI6::PlaceType>> GetFullMap() const override | |||
| { | |||
| } | |||
| [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t CellX, int32_t CellY) const override | |||
| { | |||
| } | |||
| [[nodiscard]] std::vector<std::vector<THUAI6::PlaceType>> GetFullMap() const override; | |||
| [[nodiscard]] THUAI6::PlaceType GetPlaceType(int32_t CellX, int32_t CellY) const override; | |||
| [[nodiscard]] const std::vector<int64_t> GetPlayerGUIDs() const override | |||
| { | |||
| } | |||
| [[nodiscard]] const std::vector<int64_t> GetPlayerGUIDs() const override; | |||
| std::future<bool> Attack(double angleInRadian) override | |||
| { | |||
| } | |||
| std::future<bool> CarryHuman() override | |||
| { | |||
| } | |||
| std::future<bool> ReleaseHuman() override | |||
| { | |||
| } | |||
| std::future<bool> HangHuman() override | |||
| { | |||
| } | |||
| [[nodiscard]] std::shared_ptr<const THUAI6::Butcher> GetSelfInfo() const override | |||
| { | |||
| } | |||
| std::future<bool> Attack(double angleInRadian) override; | |||
| std::future<bool> CarryHuman() override; | |||
| std::future<bool> ReleaseHuman() override; | |||
| std::future<bool> HangHuman() override; | |||
| [[nodiscard]] std::shared_ptr<const THUAI6::Butcher> GetSelfInfo() const override; | |||
| private: | |||
| ILogic& logic; | |||
| @@ -9,6 +9,8 @@ | |||
| #include <grpcpp/grpcpp.h> | |||
| #include "structures.h" | |||
| #include <thread> | |||
| #include <mutex> | |||
| #include <queue> | |||
| class Logic; | |||
| @@ -23,17 +25,15 @@ public: | |||
| bool PickProp(THUAI6::PropType prop, int64_t playerID); | |||
| bool UseProp(int64_t playerID); | |||
| bool UseSkill(int64_t playerID); | |||
| std::pair<int64_t, std::string> GetMessage(); | |||
| bool HaveMessage(); | |||
| bool SendMessage(int64_t toID, std::string message, int64_t playerID); | |||
| bool HaveMessage(int64_t playerID); | |||
| std::pair<int64_t, std::string> GetMessage(int64_t playerID); | |||
| bool Escape(int64_t playerID); | |||
| void StartFixMachine(int64_t playerID); | |||
| void EndFixMachine(); | |||
| bool GetFixStatus(); | |||
| void StartSaveHuman(int64_t playerID); | |||
| void EndSaveHuman(); | |||
| bool GetSaveStatus(); | |||
| bool StartFixMachine(int64_t playerID); | |||
| bool EndFixMachine(int64_t playerID); | |||
| bool StartSaveHuman(int64_t playerID); | |||
| bool EndSaveHuman(int64_t playerID); | |||
| bool Attack(double angle, int64_t playerID); | |||
| @@ -46,14 +46,14 @@ public: | |||
| bool HaveMessage2Client(); | |||
| void AddPlayer(int64_t playerID, THUAI6::PlayerType playerType, THUAI6::HumanType humanType, THUAI6::ButcherType butcherType); | |||
| void ReadMessage(int64_t playerID); | |||
| private: | |||
| void FixMachine(int64_t playerID); | |||
| void SaveHuman(int64_t playerID); | |||
| std::unique_ptr<protobuf::AvailableService::Stub> THUAI6Stub; | |||
| bool haveNewMessage = false; | |||
| protobuf::MessageToClient message2Client; | |||
| bool isFixing = false; | |||
| bool isSaving = false; | |||
| std::queue<std::pair<int64_t, std::string>> messageQueue; | |||
| std::mutex messageMutex; | |||
| }; | |||
| #endif | |||
| @@ -13,6 +13,7 @@ | |||
| #include <mutex> | |||
| #include <condition_variable> | |||
| #include <atomic> | |||
| #include <queue> | |||
| #include "Message2Server.pb.h" | |||
| #include "Message2Clients.pb.h" | |||
| @@ -57,26 +58,28 @@ private: | |||
| std::condition_variable cvBuffer; | |||
| std::condition_variable cvAI; | |||
| // 信息队列目前可能会不用?具体待定 | |||
| // 信息队列 | |||
| std::queue<std::pair<int64_t, std::string>> messageQueue; | |||
| // 存储状态,分别是现在的状态和缓冲区的状态。 | |||
| State state[2]; | |||
| State* currentState; | |||
| State* bufferState; | |||
| // 保存缓冲区数 | |||
| int counterState = 0; | |||
| int counterBuffer = 0; | |||
| // 是否应该执行player() | |||
| std::atomic_bool AILoop = true; | |||
| // buffer是否更新完毕 | |||
| bool bufferUpdated = true; | |||
| // 是否可以启用当前状态 | |||
| bool currentStateAccessed = false; | |||
| // 是否应当启动AI | |||
| bool AIStart = false; | |||
| // 控制内容更新的变量 | |||
| // asynchronous = true 时控制内容更新的变量 | |||
| std::atomic_bool freshed = false; | |||
| // 提供给API使用的函数 | |||
| @@ -103,33 +106,23 @@ private: | |||
| bool Escape() override; | |||
| // 说明:双向stream由三个函数共同实现,两个记录开始和结束,结果由Logic里的私有的成员变量记录,获得返回值则另调函数 | |||
| void StartFixMachine() override; | |||
| void EndFixMachine() override; | |||
| bool GetFixStatus() override; | |||
| bool StartFixMachine() override; | |||
| bool EndFixMachine() override; | |||
| void StartSaveHuman() override; | |||
| void EndSaveHuman() override; | |||
| bool GetSaveStatus() override; | |||
| bool StartSaveHuman() override; | |||
| bool EndSaveHuman() override; | |||
| bool Attack(double angle) override; | |||
| bool CarryHuman() override; | |||
| bool ReleaseHuman() override; | |||
| bool HangHuman() override; | |||
| bool WaitThread() override | |||
| { | |||
| } | |||
| bool WaitThread() override; | |||
| int GetCounter() override | |||
| { | |||
| } | |||
| int GetCounter() const override; | |||
| bool TryConnection(); | |||
| // 执行AI线程 | |||
| void PlayerWrapper(std::function<void()> player); | |||
| // THUAI5中的一系列用于处理信息的函数可能也不会再用 | |||
| void ProcessMessage(); | |||
| @@ -118,8 +118,7 @@ namespace THUAI6 | |||
| struct Human : public Player | |||
| { | |||
| bool onChair; // 是否被挂 | |||
| bool onGround; // 是否倒地 | |||
| HumanState state; // 人类状态 | |||
| int32_t life; // 剩余生命(本次倒地之前还能承受的伤害) | |||
| int32_t hangedTime; // 被挂的次数 | |||
| @@ -76,6 +76,15 @@ namespace Proto2THUAI6 | |||
| {protobuf::ButcherBuffType::BBUFFTYPE4, THUAI6::ButcherBuffType::ButcherBuffType4}, | |||
| }; | |||
| inline std::map<protobuf::HumanState, THUAI6::HumanState> humanStateDict{ | |||
| {protobuf::HumanState::NULL_STATUS, THUAI6::HumanState::NullHumanState}, | |||
| {protobuf::HumanState::IDLE, THUAI6::HumanState::Idle}, | |||
| {protobuf::HumanState::FIXING, THUAI6::HumanState::Fixing}, | |||
| {protobuf::HumanState::DYING, THUAI6::HumanState::Dying}, | |||
| {protobuf::HumanState::ON_CHAIR, THUAI6::HumanState::OnChair}, | |||
| {protobuf::HumanState::DEAD, THUAI6::HumanState::Dead}, | |||
| }; | |||
| // 用于将Protobuf中的类转换为THUAI6的类 | |||
| inline std::shared_ptr<THUAI6::Butcher> Protobuf2THUAI6Butcher(const protobuf::MessageOfButcher& butcherMsg) | |||
| { | |||
| @@ -115,8 +124,7 @@ namespace Proto2THUAI6 | |||
| human->playerType = THUAI6::PlayerType::HumanPlayer; | |||
| human->prop = propTypeDict[humanMsg.prop()]; | |||
| human->place = placeTypeDict[humanMsg.place()]; | |||
| human->onChair = humanMsg.on_chair(); | |||
| human->onGround = humanMsg.on_ground(); | |||
| human->state = humanStateDict[humanMsg.state()]; | |||
| human->life = humanMsg.life(); | |||
| human->hangedTime = humanMsg.hanged_time(); | |||
| human->humanType = humanTypeDict[humanMsg.human_type()]; | |||
| @@ -2,6 +2,9 @@ | |||
| #include <thread> | |||
| #include "AI.h" | |||
| // 为假则play()期间确保游戏状态不更新,为真则只保证游戏状态在调用相关方法时不更新 | |||
| extern const bool asynchronous = false; | |||
| // 选手必须定义该变量来选择自己的阵营 | |||
| extern const THUAI6::PlayerType playerType = THUAI6::PlayerType::HumanPlayer; | |||
| @@ -14,6 +17,7 @@ extern const THUAI6::HumanType humanType = THUAI6::HumanType::HumanType1; | |||
| void AI::play(IHumanAPI& api) | |||
| { | |||
| // api.Move(1, 1); | |||
| } | |||
| void AI::play(IButcherAPI& api) | |||
| @@ -176,44 +176,38 @@ std::vector<std::vector<THUAI6::PlaceType>> ButcherAPI::GetFullMap() const | |||
| return logic.GetFullMap(); | |||
| } | |||
| void HumanAPI::StartFixMachine() | |||
| const std::vector<int64_t> HumanAPI::GetPlayerGUIDs() const | |||
| { | |||
| std::thread([&]() | |||
| { logic.StartFixMachine(); }) | |||
| .detach(); | |||
| // todo | |||
| } | |||
| void HumanAPI::EndFixMachine() | |||
| const std::vector<int64_t> ButcherAPI::GetPlayerGUIDs() const | |||
| { | |||
| std::thread([&]() | |||
| { logic.EndFixMachine(); }) | |||
| .detach(); | |||
| // todo | |||
| } | |||
| std::future<bool> HumanAPI::GetFixStatus() | |||
| std::future<bool> HumanAPI::StartFixMachine() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.GetFixStatus(); }); | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.StartFixMachine(); }); | |||
| } | |||
| void HumanAPI::StartSaveHuman() | |||
| std::future<bool> HumanAPI::EndFixMachine() | |||
| { | |||
| std::thread([&]() | |||
| { logic.StartSaveHuman(); }) | |||
| .detach(); | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.EndFixMachine(); }); | |||
| } | |||
| void HumanAPI::EndSaveHuman() | |||
| std::future<bool> HumanAPI::StartSaveHuman() | |||
| { | |||
| std::thread([&]() | |||
| { logic.EndSaveHuman(); }) | |||
| .detach(); | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.StartSaveHuman(); }); | |||
| } | |||
| std::future<bool> HumanAPI::GetSaveStatus() | |||
| std::future<bool> HumanAPI::EndSaveHuman() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.GetSaveStatus(); }); | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.EndSaveHuman(); }); | |||
| } | |||
| std::future<bool> HumanAPI::Escape() | |||
| @@ -73,115 +73,64 @@ bool Communication::SendMessage(int64_t toID, std::string message, int64_t playe | |||
| return false; | |||
| } | |||
| bool Communication::HaveMessage(int64_t playerID) | |||
| bool Communication::Escape(int64_t playerID) | |||
| { | |||
| protobuf::BoolRes haveMessageResult; | |||
| protobuf::BoolRes escapeResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| auto status = THUAI6Stub->HaveMessage(&context, request, &haveMessageResult); | |||
| auto status = THUAI6Stub->Escape(&context, request, &escapeResult); | |||
| if (status.ok()) | |||
| return haveMessageResult.act_success(); | |||
| return escapeResult.act_success(); | |||
| else | |||
| return false; | |||
| } | |||
| std::pair<int64_t, std::string> Communication::GetMessage(int64_t playerID) | |||
| bool Communication::StartFixMachine(int64_t playerID) | |||
| { | |||
| protobuf::MsgRes getMessageResult; | |||
| protobuf::BoolRes startFixMachineResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| auto status = THUAI6Stub->GetMessage(&context, request, &getMessageResult); | |||
| auto status = THUAI6Stub->StartFixMachine(&context, request, &startFixMachineResult); | |||
| if (status.ok()) | |||
| { | |||
| if (getMessageResult.have_message()) | |||
| return std::make_pair(getMessageResult.from_player_id(), getMessageResult.message_received()); | |||
| else | |||
| return std::make_pair(-1, ""); | |||
| } | |||
| return startFixMachineResult.act_success(); | |||
| else | |||
| return std::make_pair(-1, ""); | |||
| return false; | |||
| } | |||
| bool Communication::Escape(int64_t playerID) | |||
| bool Communication::EndFixMachine(int64_t playerID) | |||
| { | |||
| protobuf::BoolRes escapeResult; | |||
| protobuf::BoolRes endFixMachineResult; | |||
| ClientContext context; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| auto status = THUAI6Stub->Escape(&context, request, &escapeResult); | |||
| auto status = THUAI6Stub->EndFixMachine(&context, request, &endFixMachineResult); | |||
| if (status.ok()) | |||
| return escapeResult.act_success(); | |||
| return endFixMachineResult.act_success(); | |||
| else | |||
| return false; | |||
| } | |||
| void Communication::FixMachine(int64_t playerID) | |||
| bool Communication::StartSaveHuman(int64_t playerID) | |||
| { | |||
| protobuf::BoolRes fixMachineResult; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| protobuf::BoolRes saveHumanResult; | |||
| ClientContext context; | |||
| while (isFixing) | |||
| { | |||
| auto fixStream = THUAI6Stub->FixMachine(&context); | |||
| fixStream->Write(request); | |||
| fixStream->Read(&fixMachineResult); | |||
| if (!fixMachineResult.act_success()) | |||
| { | |||
| isFixing = false; | |||
| break; | |||
| } | |||
| std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 防止巨量发信 | |||
| } | |||
| } | |||
| void Communication::StartFixMachine(int64_t playerID) | |||
| { | |||
| isFixing = true; | |||
| FixMachine(playerID); | |||
| } | |||
| void Communication::EndFixMachine() | |||
| { | |||
| isFixing = false; | |||
| } | |||
| bool Communication::GetFixStatus() | |||
| { | |||
| return isFixing; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| auto status = THUAI6Stub->StartSaveHuman(&context, request, &saveHumanResult); | |||
| if (status.ok()) | |||
| return saveHumanResult.act_success(); | |||
| else | |||
| return false; | |||
| } | |||
| void Communication::SaveHuman(int64_t playerID) | |||
| bool Communication::EndSaveHuman(int64_t playerID) | |||
| { | |||
| protobuf::BoolRes saveHumanResult; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| ClientContext context; | |||
| while (isSaving) | |||
| { | |||
| auto saveStream = THUAI6Stub->SaveHuman(&context); | |||
| saveStream->Write(request); | |||
| saveStream->Read(&saveHumanResult); | |||
| if (!saveHumanResult.act_success()) | |||
| { | |||
| isSaving = false; | |||
| break; | |||
| } | |||
| std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 防止巨量发信 | |||
| } | |||
| } | |||
| void Communication::StartSaveHuman(int64_t playerID) | |||
| { | |||
| isSaving = true; | |||
| SaveHuman(playerID); | |||
| } | |||
| void Communication::EndSaveHuman() | |||
| { | |||
| isSaving = false; | |||
| } | |||
| bool Communication::GetSaveStatus() | |||
| { | |||
| return isSaving; | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| auto status = THUAI6Stub->EndSaveHuman(&context, request, &saveHumanResult); | |||
| if (status.ok()) | |||
| return saveHumanResult.act_success(); | |||
| else | |||
| return false; | |||
| } | |||
| bool Communication::Attack(double angle, int64_t playerID) | |||
| @@ -239,7 +188,10 @@ bool Communication::TryConnection(int64_t playerID) | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| auto status = THUAI6Stub->TryConnection(&context, request, &reply); | |||
| if (status.ok()) | |||
| { | |||
| std::cout << "Connection success!" << std::endl; | |||
| return true; | |||
| } | |||
| else | |||
| return false; | |||
| } | |||
| @@ -255,6 +207,42 @@ bool Communication::HaveMessage2Client() | |||
| return haveNewMessage; | |||
| } | |||
| std::pair<int64_t, std::string> Communication::GetMessage() | |||
| { | |||
| std::lock_guard<std::mutex> lock(messageMutex); | |||
| if (messageQueue.empty()) | |||
| return std::make_pair(-1, ""); | |||
| else | |||
| { | |||
| auto message = messageQueue.front(); | |||
| messageQueue.pop(); | |||
| return message; | |||
| } | |||
| } | |||
| bool Communication::HaveMessage() | |||
| { | |||
| std::lock_guard<std::mutex> lock(messageMutex); | |||
| return !messageQueue.empty(); | |||
| } | |||
| void Communication::ReadMessage(int64_t playerID) | |||
| { | |||
| auto tRead = [&]() | |||
| { | |||
| auto request = THUAI62Proto::THUAI62ProtobufID(playerID); | |||
| ClientContext context; | |||
| protobuf::MsgRes messageReceived; | |||
| auto reader = THUAI6Stub->GetMessage(&context, request); | |||
| while (reader->Read(&messageReceived)) | |||
| { | |||
| std::lock_guard<std::mutex> lock(messageMutex); | |||
| messageQueue.push(std::make_pair(messageReceived.from_player_id(), messageReceived.message_received())); | |||
| } | |||
| }; | |||
| std::thread(tRead).detach(); | |||
| } | |||
| void Communication::AddPlayer(int64_t playerID, THUAI6::PlayerType playerType, THUAI6::HumanType humanType, THUAI6::ButcherType butcherType) | |||
| { | |||
| auto msgThread = [&]() | |||
| @@ -1,5 +1,254 @@ | |||
| #include "AI.h" | |||
| #include "API.h" | |||
| #define PI 3.14159265358979323846 | |||
| std::future<bool> HumanDebugAPI::Move(int64_t timeInMilliseconds, double angleInRadian) | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.Move(timeInMilliseconds, angleInRadian); }); | |||
| } | |||
| std::future<bool> HumanDebugAPI::MoveDown(int64_t timeInMilliseconds) | |||
| { | |||
| return Move(timeInMilliseconds, 0); | |||
| } | |||
| std::future<bool> HumanDebugAPI::MoveRight(int64_t timeInMilliseconds) | |||
| { | |||
| return Move(timeInMilliseconds, PI * 0.5); | |||
| } | |||
| std::future<bool> HumanDebugAPI::MoveUp(int64_t timeInMilliseconds) | |||
| { | |||
| return Move(timeInMilliseconds, PI); | |||
| } | |||
| std::future<bool> HumanDebugAPI::MoveLeft(int64_t timeInMilliseconds) | |||
| { | |||
| return Move(timeInMilliseconds, PI * 1.5); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::Move(int64_t timeInMilliseconds, double angleInRadian) | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.Move(timeInMilliseconds, angleInRadian); }); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::MoveDown(int64_t timeInMilliseconds) | |||
| { | |||
| return Move(timeInMilliseconds, 0); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::MoveRight(int64_t timeInMilliseconds) | |||
| { | |||
| return Move(timeInMilliseconds, PI * 0.5); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::MoveUp(int64_t timeInMilliseconds) | |||
| { | |||
| return Move(timeInMilliseconds, PI); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::MoveLeft(int64_t timeInMilliseconds) | |||
| { | |||
| return Move(timeInMilliseconds, PI * 1.5); | |||
| } | |||
| std::future<bool> HumanDebugAPI::PickProp(THUAI6::PropType prop) | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.PickProp(prop); }); | |||
| } | |||
| std::future<bool> HumanDebugAPI::UseProp() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.UseProp(); }); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::PickProp(THUAI6::PropType prop) | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.PickProp(prop); }); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::UseProp() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.UseProp(); }); | |||
| } | |||
| std::future<bool> HumanDebugAPI::UseSkill() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.UseSkill(); }); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::UseSkill() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.UseSkill(); }); | |||
| } | |||
| std::future<bool> HumanDebugAPI::SendMessage(int64_t toID, std::string message) | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.SendMessage(toID, message); }); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::SendMessage(int64_t toID, std::string message) | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.SendMessage(toID, message); }); | |||
| } | |||
| std::future<bool> HumanDebugAPI::HaveMessage() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.HaveMessage(); }); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::HaveMessage() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.HaveMessage(); }); | |||
| } | |||
| std::future<std::pair<int64_t, std::string>> HumanDebugAPI::GetMessage() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.GetMessage(); }); | |||
| } | |||
| std::future<std::pair<int64_t, std::string>> ButcherDebugAPI::GetMessage() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.GetMessage(); }); | |||
| } | |||
| std::vector<std::shared_ptr<const THUAI6::Butcher>> HumanDebugAPI::GetButcher() const | |||
| { | |||
| return logic.GetButchers(); | |||
| } | |||
| std::vector<std::shared_ptr<const THUAI6::Human>> HumanDebugAPI::GetHuman() const | |||
| { | |||
| return logic.GetHumans(); | |||
| } | |||
| std::vector<std::shared_ptr<const THUAI6::Butcher>> ButcherDebugAPI::GetButcher() const | |||
| { | |||
| return logic.GetButchers(); | |||
| } | |||
| std::vector<std::shared_ptr<const THUAI6::Human>> ButcherDebugAPI::GetHuman() const | |||
| { | |||
| return logic.GetHumans(); | |||
| } | |||
| std::vector<std::shared_ptr<const THUAI6::Prop>> HumanDebugAPI::GetProps() const | |||
| { | |||
| return logic.GetProps(); | |||
| } | |||
| std::vector<std::shared_ptr<const THUAI6::Prop>> ButcherDebugAPI::GetProps() const | |||
| { | |||
| return logic.GetProps(); | |||
| } | |||
| std::vector<std::vector<THUAI6::PlaceType>> HumanDebugAPI::GetFullMap() const | |||
| { | |||
| return logic.GetFullMap(); | |||
| } | |||
| THUAI6::PlaceType HumanDebugAPI::GetPlaceType(int32_t CellX, int32_t CellY) const | |||
| { | |||
| return logic.GetPlaceType(CellX, CellY); | |||
| } | |||
| THUAI6::PlaceType ButcherDebugAPI::GetPlaceType(int32_t CellX, int32_t CellY) const | |||
| { | |||
| return logic.GetPlaceType(CellX, CellY); | |||
| } | |||
| std::vector<std::vector<THUAI6::PlaceType>> ButcherDebugAPI::GetFullMap() const | |||
| { | |||
| return logic.GetFullMap(); | |||
| } | |||
| const std::vector<int64_t> HumanDebugAPI::GetPlayerGUIDs() const | |||
| { | |||
| // todo | |||
| } | |||
| const std::vector<int64_t> ButcherDebugAPI::GetPlayerGUIDs() const | |||
| { | |||
| // todo | |||
| } | |||
| std::future<bool> HumanDebugAPI::StartFixMachine() | |||
| { | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.StartFixMachine(); }); | |||
| } | |||
| std::future<bool> HumanDebugAPI::EndFixMachine() | |||
| { | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.EndFixMachine(); }); | |||
| } | |||
| std::future<bool> HumanDebugAPI::StartSaveHuman() | |||
| { | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.StartSaveHuman(); }); | |||
| } | |||
| std::future<bool> HumanDebugAPI::EndSaveHuman() | |||
| { | |||
| std::async(std::launch::async, [&]() | |||
| { return logic.EndSaveHuman(); }); | |||
| } | |||
| std::future<bool> HumanDebugAPI::Escape() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.Escape(); }); | |||
| } | |||
| std::shared_ptr<const THUAI6::Human> HumanDebugAPI::GetSelfInfo() const | |||
| { | |||
| return logic.HumanGetSelfInfo(); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::Attack(double angleInRadian) | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.Attack(angleInRadian); }); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::CarryHuman() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.CarryHuman(); }); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::ReleaseHuman() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.ReleaseHuman(); }); | |||
| } | |||
| std::future<bool> ButcherDebugAPI::HangHuman() | |||
| { | |||
| return std::async(std::launch::async, [&]() | |||
| { return logic.HangHuman(); }); | |||
| } | |||
| std::shared_ptr<const THUAI6::Butcher> ButcherDebugAPI::GetSelfInfo() const | |||
| { | |||
| return logic.ButcherGetSelfInfo(); | |||
| } | |||
| void HumanDebugAPI::Play(IAI& ai) | |||
| { | |||
| @@ -5,9 +5,7 @@ | |||
| #include "utils.hpp" | |||
| #include "Communication.h" | |||
| // using grpc::ClientContext; | |||
| // using grpc::Status; | |||
| extern const bool asynchronous; | |||
| extern const THUAI6::PlayerType playerType; | |||
| Logic::Logic(THUAI6::PlayerType type, int64_t ID, THUAI6::ButcherType butcher, THUAI6::HumanType human) : | |||
| @@ -22,7 +20,7 @@ Logic::Logic(THUAI6::PlayerType type, int64_t ID, THUAI6::ButcherType butcher, T | |||
| std::vector<std::shared_ptr<const THUAI6::Butcher>> Logic::GetButchers() const | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxState); | |||
| std::lock_guard<std::mutex> lock(mtxBuffer); | |||
| std::vector<std::shared_ptr<const THUAI6::Butcher>> temp; | |||
| temp.assign(currentState->butchers.begin(), currentState->butchers.end()); | |||
| return temp; | |||
| @@ -30,7 +28,7 @@ std::vector<std::shared_ptr<const THUAI6::Butcher>> Logic::GetButchers() const | |||
| std::vector<std::shared_ptr<const THUAI6::Human>> Logic::GetHumans() const | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxState); | |||
| std::unique_lock<std::mutex> lock(mtxBuffer); | |||
| std::vector<std::shared_ptr<const THUAI6::Human>> temp; | |||
| temp.assign(currentState->humans.begin(), currentState->humans.end()); | |||
| return temp; | |||
| @@ -38,7 +36,7 @@ std::vector<std::shared_ptr<const THUAI6::Human>> Logic::GetHumans() const | |||
| std::vector<std::shared_ptr<const THUAI6::Prop>> Logic::GetProps() const | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxState); | |||
| std::unique_lock<std::mutex> lock(mtxBuffer); | |||
| std::vector<std::shared_ptr<const THUAI6::Prop>> temp; | |||
| temp.assign(currentState->props.begin(), currentState->props.end()); | |||
| return temp; | |||
| @@ -46,25 +44,25 @@ std::vector<std::shared_ptr<const THUAI6::Prop>> Logic::GetProps() const | |||
| std::shared_ptr<const THUAI6::Human> Logic::HumanGetSelfInfo() const | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxState); | |||
| std::unique_lock<std::mutex> lock(mtxBuffer); | |||
| return currentState->humanSelf; | |||
| } | |||
| std::shared_ptr<const THUAI6::Butcher> Logic::ButcherGetSelfInfo() const | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxState); | |||
| std::unique_lock<std::mutex> lock(mtxBuffer); | |||
| return currentState->butcherSelf; | |||
| } | |||
| std::vector<std::vector<THUAI6::PlaceType>> Logic::GetFullMap() const | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxState); | |||
| std::unique_lock<std::mutex> lock(mtxBuffer); | |||
| return currentState->gamemap; | |||
| } | |||
| THUAI6::PlaceType Logic::GetPlaceType(int32_t CellX, int32_t CellY) const | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxState); | |||
| std::unique_lock<std::mutex> lock(mtxBuffer); | |||
| return currentState->gamemap[CellX][CellY]; | |||
| } | |||
| @@ -95,12 +93,12 @@ bool Logic::SendMessage(int64_t toID, std::string message) | |||
| bool Logic::HaveMessage() | |||
| { | |||
| return pComm->HaveMessage(playerID); | |||
| return pComm->HaveMessage(); | |||
| } | |||
| std::pair<int64_t, std::string> Logic::GetMessage() | |||
| { | |||
| return pComm->GetMessage(playerID); | |||
| return pComm->GetMessage(); | |||
| } | |||
| bool Logic::Escape() | |||
| @@ -108,34 +106,24 @@ bool Logic::Escape() | |||
| return pComm->Escape(playerID); | |||
| } | |||
| void Logic::StartFixMachine() | |||
| { | |||
| pComm->StartFixMachine(playerID); | |||
| } | |||
| void Logic::EndFixMachine() | |||
| { | |||
| pComm->EndFixMachine(); | |||
| } | |||
| bool Logic::GetFixStatus() | |||
| bool Logic::StartFixMachine() | |||
| { | |||
| return pComm->GetFixStatus(); | |||
| return pComm->StartFixMachine(playerID); | |||
| } | |||
| void Logic::StartSaveHuman() | |||
| bool Logic::EndFixMachine() | |||
| { | |||
| pComm->StartSaveHuman(playerID); | |||
| return pComm->EndFixMachine(playerID); | |||
| } | |||
| void Logic::EndSaveHuman() | |||
| bool Logic::StartSaveHuman() | |||
| { | |||
| pComm->EndSaveHuman(); | |||
| return pComm->StartSaveHuman(playerID); | |||
| } | |||
| bool Logic::GetSaveStatus() | |||
| bool Logic::EndSaveHuman() | |||
| { | |||
| return pComm->GetSaveStatus(); | |||
| return pComm->EndSaveHuman(playerID); | |||
| } | |||
| bool Logic::Attack(double angle) | |||
| @@ -158,22 +146,16 @@ bool Logic::HangHuman() | |||
| return pComm->HangHuman(playerID); | |||
| } | |||
| bool Logic::WaitThread() | |||
| { | |||
| Update(); | |||
| return true; | |||
| } | |||
| void Logic::ProcessMessage() | |||
| { | |||
| auto messageThread = [&]() | |||
| { | |||
| // // 首先设置消息、通过加入游戏,开始与服务端建立联系 | |||
| // protobuf::MessageToClient clientMsg; | |||
| // protobuf::PlayerMsg playerMsg = THUAI62Proto::THUAI62ProtobufPlayer(playerID, playerType, humanType, butcherType); | |||
| // grpc::ClientContext context; | |||
| // auto MessageReader = THUAI6Stub->AddPlayer(&context, playerMsg); | |||
| // // 持续读取服务端的消息 | |||
| // while (MessageReader->Read(&clientMsg)) | |||
| // { | |||
| // LoadBuffer(clientMsg); | |||
| // } | |||
| std::cout << "Join Player!" << std::endl; | |||
| pComm->AddPlayer(playerID, playerType, humanType, butcherType); | |||
| while (true) | |||
| @@ -229,27 +211,77 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message) | |||
| } | |||
| bufferState->gamemap = Proto2THUAI6::Protobuf2THUAI6Map(message.map_message()); | |||
| cvBuffer.notify_one(); | |||
| if (asynchronous) | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxState); | |||
| std::swap(currentState, bufferState); | |||
| } | |||
| freshed = true; | |||
| } | |||
| else | |||
| bufferUpdated = true; | |||
| counterBuffer++; | |||
| } | |||
| // 唤醒其他线程 | |||
| cvBuffer.notify_one(); | |||
| } | |||
| void Logic::Update() noexcept | |||
| { | |||
| if (!asynchronous) | |||
| { | |||
| std::unique_lock<std::mutex> lock(mtxBuffer); | |||
| // 缓冲区被更新之后才可以使用 | |||
| cvBuffer.wait(lock, [&]() | |||
| { return bufferUpdated; }); | |||
| std::swap(currentState, bufferState); | |||
| bufferUpdated = false; | |||
| counterState = counterBuffer; | |||
| } | |||
| } | |||
| void Logic::PlayerWrapper(std::function<void()> player) | |||
| void Logic::Wait() noexcept | |||
| { | |||
| // { | |||
| // std::unique_lock<std::mutex> lock(mtxAI); | |||
| // cvAI.wait(lock, [this]() | |||
| // { return AIStart; }); | |||
| // } | |||
| player(); | |||
| freshed = false; | |||
| { | |||
| std::unique_lock<std::mutex> lock(mtxBuffer); | |||
| cvBuffer.wait(lock, [&]() | |||
| { return freshed.load(); }); | |||
| } | |||
| } | |||
| void Logic::UnBlockAI() | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxAI); | |||
| AIStart = true; | |||
| } | |||
| cvAI.notify_one(); | |||
| } | |||
| void Logic::UnBlockBuffer() | |||
| { | |||
| { | |||
| std::lock_guard<std::mutex> lock(mtxBuffer); | |||
| bufferUpdated = true; | |||
| } | |||
| cvBuffer.notify_one(); | |||
| } | |||
| int Logic::GetCounter() const | |||
| { | |||
| std::unique_lock<std::mutex> lock(mtxState); | |||
| return counterState; | |||
| } | |||
| bool Logic::TryConnection() | |||
| { | |||
| return pComm->TryConnection(playerID); | |||
| std::cout << "Trying to connect to server..." << std::endl; | |||
| bool result = pComm->TryConnection(playerID); | |||
| return result; | |||
| } | |||
| void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port) | |||
| @@ -267,8 +299,14 @@ void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port) | |||
| timer = std::make_unique<ButcherAPI>(*this); | |||
| // 构造AI线程 | |||
| auto AIThread = [&, this]() | |||
| auto AIThread = [&]() | |||
| { | |||
| { | |||
| std::unique_lock<std::mutex> lock(mtxAI); | |||
| cvAI.wait(lock, [this]() | |||
| { return AIStart; }); | |||
| } | |||
| std::cout << "AI Start!" << std::endl; | |||
| auto ai = createAI(); | |||
| ProcessMessage(); | |||
| while (AILoop) | |||
| @@ -280,7 +318,7 @@ void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port) | |||
| } | |||
| }; | |||
| tAI = std::thread(&Logic::PlayerWrapper, this, AIThread); | |||
| tAI = std::thread(AIThread); | |||
| // 连接服务器 | |||
| if (TryConnection()) | |||
| @@ -289,11 +327,14 @@ void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port) | |||
| if (tAI.joinable()) | |||
| { | |||
| std::cout << "Join the AI thread." << std::endl; | |||
| AIStart = true; | |||
| cvAI.notify_one(); | |||
| tAI.join(); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| std::cout << "Connection error!" << std::endl; | |||
| return; | |||
| } | |||
| } | |||
| @@ -6,12 +6,14 @@ | |||
| #pragma warning(disable : 4996) | |||
| #endif | |||
| extern const bool asynchronous; | |||
| int THUAI6Main(CreateAIFunc AIBuilder) | |||
| { | |||
| // 仅供调试使用 | |||
| int playerID = 123; | |||
| std::string sIP = "localhost"; | |||
| std::string sPort = "12345"; | |||
| std::string sIP = "183.172.208.84"; | |||
| std::string sPort = "8888"; | |||
| extern const THUAI6::PlayerType playerType; | |||
| extern const THUAI6::ButcherType butcherType; | |||
| extern const THUAI6::HumanType humanType; | |||
| @@ -30,11 +30,10 @@ namespace protobuf | |||
| "/protobuf.AvailableService/UseProp", | |||
| "/protobuf.AvailableService/UseSkill", | |||
| "/protobuf.AvailableService/SendMessage", | |||
| "/protobuf.AvailableService/HaveMessage", | |||
| "/protobuf.AvailableService/GetMessage", | |||
| "/protobuf.AvailableService/StartFixMachine", | |||
| "/protobuf.AvailableService/EndFixMachine", | |||
| "/protobuf.AvailableService/SaveHuman", | |||
| "/protobuf.AvailableService/StartSaveHuman", | |||
| "/protobuf.AvailableService/EndSaveHuman", | |||
| "/protobuf.AvailableService/Attack", | |||
| "/protobuf.AvailableService/CarryHuman", | |||
| @@ -59,17 +58,16 @@ namespace protobuf | |||
| rpcmethod_UseProp_(AvailableService_method_names[4], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_UseSkill_(AvailableService_method_names[5], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_SendMessage_(AvailableService_method_names[6], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_HaveMessage_(AvailableService_method_names[7], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_GetMessage_(AvailableService_method_names[8], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_StartFixMachine_(AvailableService_method_names[9], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_EndFixMachine_(AvailableService_method_names[10], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_SaveHuman_(AvailableService_method_names[11], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_EndSaveHuman_(AvailableService_method_names[12], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_Attack_(AvailableService_method_names[13], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_CarryHuman_(AvailableService_method_names[14], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_ReleaseHuman_(AvailableService_method_names[15], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_HangHuman_(AvailableService_method_names[16], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_Escape_(AvailableService_method_names[17], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel) | |||
| rpcmethod_GetMessage_(AvailableService_method_names[7], options.suffix_for_stats(), ::grpc::internal::RpcMethod::SERVER_STREAMING, channel), | |||
| rpcmethod_StartFixMachine_(AvailableService_method_names[8], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_EndFixMachine_(AvailableService_method_names[9], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_StartSaveHuman_(AvailableService_method_names[10], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_EndSaveHuman_(AvailableService_method_names[11], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_Attack_(AvailableService_method_names[12], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_CarryHuman_(AvailableService_method_names[13], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_ReleaseHuman_(AvailableService_method_names[14], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_HangHuman_(AvailableService_method_names[15], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel), | |||
| rpcmethod_Escape_(AvailableService_method_names[16], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel) | |||
| { | |||
| } | |||
| @@ -261,60 +259,24 @@ namespace protobuf | |||
| return result; | |||
| } | |||
| ::grpc::Status AvailableService::Stub::HaveMessage(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::protobuf::BoolRes* response) | |||
| ::grpc::ClientReader<::protobuf::MsgRes>* AvailableService::Stub::GetMessageRaw(::grpc::ClientContext* context, const ::protobuf::IDMsg& request) | |||
| { | |||
| return ::grpc::internal::BlockingUnaryCall<::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_HaveMessage_, context, request, response); | |||
| return ::grpc::internal::ClientReaderFactory<::protobuf::MsgRes>::Create(channel_.get(), rpcmethod_GetMessage_, context, request); | |||
| } | |||
| void AvailableService::Stub::async::HaveMessage(::grpc::ClientContext* context, const ::protobuf::IDMsg* request, ::protobuf::BoolRes* response, std::function<void(::grpc::Status)> f) | |||
| void AvailableService::Stub::async::GetMessage(::grpc::ClientContext* context, const ::protobuf::IDMsg* request, ::grpc::ClientReadReactor<::protobuf::MsgRes>* reactor) | |||
| { | |||
| ::grpc::internal::CallbackUnaryCall<::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_HaveMessage_, context, request, response, std::move(f)); | |||
| ::grpc::internal::ClientCallbackReaderFactory<::protobuf::MsgRes>::Create(stub_->channel_.get(), stub_->rpcmethod_GetMessage_, context, request, reactor); | |||
| } | |||
| void AvailableService::Stub::async::HaveMessage(::grpc::ClientContext* context, const ::protobuf::IDMsg* request, ::protobuf::BoolRes* response, ::grpc::ClientUnaryReactor* reactor) | |||
| ::grpc::ClientAsyncReader<::protobuf::MsgRes>* AvailableService::Stub::AsyncGetMessageRaw(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::grpc::CompletionQueue* cq, void* tag) | |||
| { | |||
| ::grpc::internal::ClientCallbackUnaryFactory::Create<::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_HaveMessage_, context, request, response, reactor); | |||
| return ::grpc::internal::ClientAsyncReaderFactory<::protobuf::MsgRes>::Create(channel_.get(), cq, rpcmethod_GetMessage_, context, request, true, tag); | |||
| } | |||
| ::grpc::ClientAsyncResponseReader<::protobuf::BoolRes>* AvailableService::Stub::PrepareAsyncHaveMessageRaw(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::grpc::CompletionQueue* cq) | |||
| ::grpc::ClientAsyncReader<::protobuf::MsgRes>* AvailableService::Stub::PrepareAsyncGetMessageRaw(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::grpc::CompletionQueue* cq) | |||
| { | |||
| return ::grpc::internal::ClientAsyncResponseReaderHelper::Create<::protobuf::BoolRes, ::protobuf::IDMsg, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_HaveMessage_, context, request); | |||
| } | |||
| ::grpc::ClientAsyncResponseReader<::protobuf::BoolRes>* AvailableService::Stub::AsyncHaveMessageRaw(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::grpc::CompletionQueue* cq) | |||
| { | |||
| auto* result = | |||
| this->PrepareAsyncHaveMessageRaw(context, request, cq); | |||
| result->StartCall(); | |||
| return result; | |||
| } | |||
| ::grpc::Status AvailableService::Stub::GetMessage(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::protobuf::MsgRes* response) | |||
| { | |||
| return ::grpc::internal::BlockingUnaryCall<::protobuf::IDMsg, ::protobuf::MsgRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_GetMessage_, context, request, response); | |||
| } | |||
| void AvailableService::Stub::async::GetMessage(::grpc::ClientContext* context, const ::protobuf::IDMsg* request, ::protobuf::MsgRes* response, std::function<void(::grpc::Status)> f) | |||
| { | |||
| ::grpc::internal::CallbackUnaryCall<::protobuf::IDMsg, ::protobuf::MsgRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GetMessage_, context, request, response, std::move(f)); | |||
| } | |||
| void AvailableService::Stub::async::GetMessage(::grpc::ClientContext* context, const ::protobuf::IDMsg* request, ::protobuf::MsgRes* response, ::grpc::ClientUnaryReactor* reactor) | |||
| { | |||
| ::grpc::internal::ClientCallbackUnaryFactory::Create<::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GetMessage_, context, request, response, reactor); | |||
| } | |||
| ::grpc::ClientAsyncResponseReader<::protobuf::MsgRes>* AvailableService::Stub::PrepareAsyncGetMessageRaw(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::grpc::CompletionQueue* cq) | |||
| { | |||
| return ::grpc::internal::ClientAsyncResponseReaderHelper::Create<::protobuf::MsgRes, ::protobuf::IDMsg, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_GetMessage_, context, request); | |||
| } | |||
| ::grpc::ClientAsyncResponseReader<::protobuf::MsgRes>* AvailableService::Stub::AsyncGetMessageRaw(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::grpc::CompletionQueue* cq) | |||
| { | |||
| auto* result = | |||
| this->PrepareAsyncGetMessageRaw(context, request, cq); | |||
| result->StartCall(); | |||
| return result; | |||
| return ::grpc::internal::ClientAsyncReaderFactory<::protobuf::MsgRes>::Create(channel_.get(), cq, rpcmethod_GetMessage_, context, request, false, nullptr); | |||
| } | |||
| ::grpc::Status AvailableService::Stub::StartFixMachine(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::protobuf::BoolRes* response) | |||
| @@ -373,30 +335,30 @@ namespace protobuf | |||
| return result; | |||
| } | |||
| ::grpc::Status AvailableService::Stub::SaveHuman(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::protobuf::BoolRes* response) | |||
| ::grpc::Status AvailableService::Stub::StartSaveHuman(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::protobuf::BoolRes* response) | |||
| { | |||
| return ::grpc::internal::BlockingUnaryCall<::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_SaveHuman_, context, request, response); | |||
| return ::grpc::internal::BlockingUnaryCall<::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_StartSaveHuman_, context, request, response); | |||
| } | |||
| void AvailableService::Stub::async::SaveHuman(::grpc::ClientContext* context, const ::protobuf::IDMsg* request, ::protobuf::BoolRes* response, std::function<void(::grpc::Status)> f) | |||
| void AvailableService::Stub::async::StartSaveHuman(::grpc::ClientContext* context, const ::protobuf::IDMsg* request, ::protobuf::BoolRes* response, std::function<void(::grpc::Status)> f) | |||
| { | |||
| ::grpc::internal::CallbackUnaryCall<::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_SaveHuman_, context, request, response, std::move(f)); | |||
| ::grpc::internal::CallbackUnaryCall<::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_StartSaveHuman_, context, request, response, std::move(f)); | |||
| } | |||
| void AvailableService::Stub::async::SaveHuman(::grpc::ClientContext* context, const ::protobuf::IDMsg* request, ::protobuf::BoolRes* response, ::grpc::ClientUnaryReactor* reactor) | |||
| void AvailableService::Stub::async::StartSaveHuman(::grpc::ClientContext* context, const ::protobuf::IDMsg* request, ::protobuf::BoolRes* response, ::grpc::ClientUnaryReactor* reactor) | |||
| { | |||
| ::grpc::internal::ClientCallbackUnaryFactory::Create<::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_SaveHuman_, context, request, response, reactor); | |||
| ::grpc::internal::ClientCallbackUnaryFactory::Create<::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_StartSaveHuman_, context, request, response, reactor); | |||
| } | |||
| ::grpc::ClientAsyncResponseReader<::protobuf::BoolRes>* AvailableService::Stub::PrepareAsyncSaveHumanRaw(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::grpc::CompletionQueue* cq) | |||
| ::grpc::ClientAsyncResponseReader<::protobuf::BoolRes>* AvailableService::Stub::PrepareAsyncStartSaveHumanRaw(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::grpc::CompletionQueue* cq) | |||
| { | |||
| return ::grpc::internal::ClientAsyncResponseReaderHelper::Create<::protobuf::BoolRes, ::protobuf::IDMsg, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_SaveHuman_, context, request); | |||
| return ::grpc::internal::ClientAsyncResponseReaderHelper::Create<::protobuf::BoolRes, ::protobuf::IDMsg, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_StartSaveHuman_, context, request); | |||
| } | |||
| ::grpc::ClientAsyncResponseReader<::protobuf::BoolRes>* AvailableService::Stub::AsyncSaveHumanRaw(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::grpc::CompletionQueue* cq) | |||
| ::grpc::ClientAsyncResponseReader<::protobuf::BoolRes>* AvailableService::Stub::AsyncStartSaveHumanRaw(::grpc::ClientContext* context, const ::protobuf::IDMsg& request, ::grpc::CompletionQueue* cq) | |||
| { | |||
| auto* result = | |||
| this->PrepareAsyncSaveHumanRaw(context, request, cq); | |||
| this->PrepareAsyncStartSaveHumanRaw(context, request, cq); | |||
| result->StartCall(); | |||
| return result; | |||
| } | |||
| @@ -671,14 +633,14 @@ namespace protobuf | |||
| )); | |||
| AddMethod(new ::grpc::internal::RpcServiceMethod( | |||
| AvailableService_method_names[7], | |||
| ::grpc::internal::RpcMethod::NORMAL_RPC, | |||
| new ::grpc::internal::RpcMethodHandler<AvailableService::Service, ::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( | |||
| ::grpc::internal::RpcMethod::SERVER_STREAMING, | |||
| new ::grpc::internal::ServerStreamingHandler<AvailableService::Service, ::protobuf::IDMsg, ::protobuf::MsgRes>( | |||
| [](AvailableService::Service* service, | |||
| ::grpc::ServerContext* ctx, | |||
| const ::protobuf::IDMsg* req, | |||
| ::protobuf::BoolRes* resp) | |||
| ::grpc::ServerWriter<::protobuf::MsgRes>* writer) | |||
| { | |||
| return service->HaveMessage(ctx, req, resp); | |||
| return service->GetMessage(ctx, req, writer); | |||
| }, | |||
| this | |||
| ) | |||
| @@ -686,20 +648,6 @@ namespace protobuf | |||
| AddMethod(new ::grpc::internal::RpcServiceMethod( | |||
| AvailableService_method_names[8], | |||
| ::grpc::internal::RpcMethod::NORMAL_RPC, | |||
| new ::grpc::internal::RpcMethodHandler<AvailableService::Service, ::protobuf::IDMsg, ::protobuf::MsgRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( | |||
| [](AvailableService::Service* service, | |||
| ::grpc::ServerContext* ctx, | |||
| const ::protobuf::IDMsg* req, | |||
| ::protobuf::MsgRes* resp) | |||
| { | |||
| return service->GetMessage(ctx, req, resp); | |||
| }, | |||
| this | |||
| ) | |||
| )); | |||
| AddMethod(new ::grpc::internal::RpcServiceMethod( | |||
| AvailableService_method_names[9], | |||
| ::grpc::internal::RpcMethod::NORMAL_RPC, | |||
| new ::grpc::internal::RpcMethodHandler<AvailableService::Service, ::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( | |||
| [](AvailableService::Service* service, | |||
| ::grpc::ServerContext* ctx, | |||
| @@ -712,7 +660,7 @@ namespace protobuf | |||
| ) | |||
| )); | |||
| AddMethod(new ::grpc::internal::RpcServiceMethod( | |||
| AvailableService_method_names[10], | |||
| AvailableService_method_names[9], | |||
| ::grpc::internal::RpcMethod::NORMAL_RPC, | |||
| new ::grpc::internal::RpcMethodHandler<AvailableService::Service, ::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( | |||
| [](AvailableService::Service* service, | |||
| @@ -726,7 +674,7 @@ namespace protobuf | |||
| ) | |||
| )); | |||
| AddMethod(new ::grpc::internal::RpcServiceMethod( | |||
| AvailableService_method_names[11], | |||
| AvailableService_method_names[10], | |||
| ::grpc::internal::RpcMethod::NORMAL_RPC, | |||
| new ::grpc::internal::RpcMethodHandler<AvailableService::Service, ::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( | |||
| [](AvailableService::Service* service, | |||
| @@ -734,13 +682,13 @@ namespace protobuf | |||
| const ::protobuf::IDMsg* req, | |||
| ::protobuf::BoolRes* resp) | |||
| { | |||
| return service->SaveHuman(ctx, req, resp); | |||
| return service->StartSaveHuman(ctx, req, resp); | |||
| }, | |||
| this | |||
| ) | |||
| )); | |||
| AddMethod(new ::grpc::internal::RpcServiceMethod( | |||
| AvailableService_method_names[12], | |||
| AvailableService_method_names[11], | |||
| ::grpc::internal::RpcMethod::NORMAL_RPC, | |||
| new ::grpc::internal::RpcMethodHandler<AvailableService::Service, ::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( | |||
| [](AvailableService::Service* service, | |||
| @@ -754,7 +702,7 @@ namespace protobuf | |||
| ) | |||
| )); | |||
| AddMethod(new ::grpc::internal::RpcServiceMethod( | |||
| AvailableService_method_names[13], | |||
| AvailableService_method_names[12], | |||
| ::grpc::internal::RpcMethod::NORMAL_RPC, | |||
| new ::grpc::internal::RpcMethodHandler<AvailableService::Service, ::protobuf::AttackMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( | |||
| [](AvailableService::Service* service, | |||
| @@ -768,7 +716,7 @@ namespace protobuf | |||
| ) | |||
| )); | |||
| AddMethod(new ::grpc::internal::RpcServiceMethod( | |||
| AvailableService_method_names[14], | |||
| AvailableService_method_names[13], | |||
| ::grpc::internal::RpcMethod::NORMAL_RPC, | |||
| new ::grpc::internal::RpcMethodHandler<AvailableService::Service, ::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( | |||
| [](AvailableService::Service* service, | |||
| @@ -782,7 +730,7 @@ namespace protobuf | |||
| ) | |||
| )); | |||
| AddMethod(new ::grpc::internal::RpcServiceMethod( | |||
| AvailableService_method_names[15], | |||
| AvailableService_method_names[14], | |||
| ::grpc::internal::RpcMethod::NORMAL_RPC, | |||
| new ::grpc::internal::RpcMethodHandler<AvailableService::Service, ::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( | |||
| [](AvailableService::Service* service, | |||
| @@ -796,7 +744,7 @@ namespace protobuf | |||
| ) | |||
| )); | |||
| AddMethod(new ::grpc::internal::RpcServiceMethod( | |||
| AvailableService_method_names[16], | |||
| AvailableService_method_names[15], | |||
| ::grpc::internal::RpcMethod::NORMAL_RPC, | |||
| new ::grpc::internal::RpcMethodHandler<AvailableService::Service, ::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( | |||
| [](AvailableService::Service* service, | |||
| @@ -810,7 +758,7 @@ namespace protobuf | |||
| ) | |||
| )); | |||
| AddMethod(new ::grpc::internal::RpcServiceMethod( | |||
| AvailableService_method_names[17], | |||
| AvailableService_method_names[16], | |||
| ::grpc::internal::RpcMethod::NORMAL_RPC, | |||
| new ::grpc::internal::RpcMethodHandler<AvailableService::Service, ::protobuf::IDMsg, ::protobuf::BoolRes, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( | |||
| [](AvailableService::Service* service, | |||
| @@ -885,19 +833,11 @@ namespace protobuf | |||
| return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); | |||
| } | |||
| ::grpc::Status AvailableService::Service::HaveMessage(::grpc::ServerContext* context, const ::protobuf::IDMsg* request, ::protobuf::BoolRes* response) | |||
| ::grpc::Status AvailableService::Service::GetMessage(::grpc::ServerContext* context, const ::protobuf::IDMsg* request, ::grpc::ServerWriter<::protobuf::MsgRes>* writer) | |||
| { | |||
| (void)context; | |||
| (void)request; | |||
| (void)response; | |||
| return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); | |||
| } | |||
| ::grpc::Status AvailableService::Service::GetMessage(::grpc::ServerContext* context, const ::protobuf::IDMsg* request, ::protobuf::MsgRes* response) | |||
| { | |||
| (void)context; | |||
| (void)request; | |||
| (void)response; | |||
| (void)writer; | |||
| return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); | |||
| } | |||
| @@ -917,7 +857,7 @@ namespace protobuf | |||
| return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); | |||
| } | |||
| ::grpc::Status AvailableService::Service::SaveHuman(::grpc::ServerContext* context, const ::protobuf::IDMsg* request, ::protobuf::BoolRes* response) | |||
| ::grpc::Status AvailableService::Service::StartSaveHuman(::grpc::ServerContext* context, const ::protobuf::IDMsg* request, ::protobuf::BoolRes* response) | |||
| { | |||
| (void)context; | |||
| (void)request; | |||
| @@ -31,7 +31,7 @@ static constexpr ::_pb::Message* const* file_default_instances = nullptr; | |||
| const char descriptor_table_protodef_Services_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = | |||
| "\n\016Services.proto\022\010protobuf\032\025Message2Clie" | |||
| "nts.proto\032\024Message2Server.proto2\246\007\n\020Avai" | |||
| "nts.proto\032\024Message2Server.proto2\372\006\n\020Avai" | |||
| "lableService\0223\n\rTryConnection\022\017.protobuf" | |||
| ".IDMsg\032\021.protobuf.BoolRes\022=\n\tAddPlayer\022\023" | |||
| ".protobuf.PlayerMsg\032\031.protobuf.MessageTo" | |||
| @@ -41,21 +41,20 @@ const char descriptor_table_protodef_Services_2eproto[] PROTOBUF_SECTION_VARIABL | |||
| "otobuf.IDMsg\032\021.protobuf.BoolRes\022.\n\010UseSk" | |||
| "ill\022\017.protobuf.IDMsg\032\021.protobuf.BoolRes\022" | |||
| "3\n\013SendMessage\022\021.protobuf.SendMsg\032\021.prot" | |||
| "obuf.BoolRes\0221\n\013HaveMessage\022\017.protobuf.I" | |||
| "DMsg\032\021.protobuf.BoolRes\022/\n\nGetMessage\022\017." | |||
| "protobuf.IDMsg\032\020.protobuf.MsgRes\0225\n\017Star" | |||
| "tFixMachine\022\017.protobuf.IDMsg\032\021.protobuf." | |||
| "BoolRes\0223\n\rEndFixMachine\022\017.protobuf.IDMs" | |||
| "g\032\021.protobuf.BoolRes\022/\n\tSaveHuman\022\017.prot" | |||
| "obuf.IDMsg\032\021.protobuf.BoolRes\0222\n\014EndSave" | |||
| "Human\022\017.protobuf.IDMsg\032\021.protobuf.BoolRe" | |||
| "s\0220\n\006Attack\022\023.protobuf.AttackMsg\032\021.proto" | |||
| "buf.BoolRes\0220\n\nCarryHuman\022\017.protobuf.IDM" | |||
| "sg\032\021.protobuf.BoolRes\0222\n\014ReleaseHuman\022\017." | |||
| "protobuf.IDMsg\032\021.protobuf.BoolRes\022/\n\tHan" | |||
| "gHuman\022\017.protobuf.IDMsg\032\021.protobuf.BoolR" | |||
| "es\022,\n\006Escape\022\017.protobuf.IDMsg\032\021.protobuf" | |||
| ".BoolResb\006proto3"; | |||
| "obuf.BoolRes\0221\n\nGetMessage\022\017.protobuf.ID" | |||
| "Msg\032\020.protobuf.MsgRes0\001\0225\n\017StartFixMachi" | |||
| "ne\022\017.protobuf.IDMsg\032\021.protobuf.BoolRes\0223" | |||
| "\n\rEndFixMachine\022\017.protobuf.IDMsg\032\021.proto" | |||
| "buf.BoolRes\0224\n\016StartSaveHuman\022\017.protobuf" | |||
| ".IDMsg\032\021.protobuf.BoolRes\0222\n\014EndSaveHuma" | |||
| "n\022\017.protobuf.IDMsg\032\021.protobuf.BoolRes\0220\n" | |||
| "\006Attack\022\023.protobuf.AttackMsg\032\021.protobuf." | |||
| "BoolRes\0220\n\nCarryHuman\022\017.protobuf.IDMsg\032\021" | |||
| ".protobuf.BoolRes\0222\n\014ReleaseHuman\022\017.prot" | |||
| "obuf.IDMsg\032\021.protobuf.BoolRes\022/\n\tHangHum" | |||
| "an\022\017.protobuf.IDMsg\032\021.protobuf.BoolRes\022," | |||
| "\n\006Escape\022\017.protobuf.IDMsg\032\021.protobuf.Boo" | |||
| "lResb\006proto3"; | |||
| static const ::_pbi::DescriptorTable* const descriptor_table_Services_2eproto_deps[2] = { | |||
| &::descriptor_table_Message2Clients_2eproto, | |||
| &::descriptor_table_Message2Server_2eproto, | |||
| @@ -64,7 +63,7 @@ static ::_pbi::once_flag descriptor_table_Services_2eproto_once; | |||
| const ::_pbi::DescriptorTable descriptor_table_Services_2eproto = { | |||
| false, | |||
| false, | |||
| 1016, | |||
| 972, | |||
| descriptor_table_protodef_Services_2eproto, | |||
| "Services.proto", | |||
| &descriptor_table_Services_2eproto_once, | |||
| @@ -0,0 +1,34 @@ | |||
| <Project Sdk="Microsoft.NET.Sdk"> | |||
| <PropertyGroup> | |||
| <TargetFramework>net6.0</TargetFramework> | |||
| <ImplicitUsings>enable</ImplicitUsings> | |||
| <Nullable>enable</Nullable> | |||
| </PropertyGroup> | |||
| <!--<ItemGroup> | |||
| <None Remove="Message2Clients.proto" /> | |||
| <None Remove="Message2Server.proto" /> | |||
| <None Remove="MessageType.proto" /> | |||
| <None Remove="Services.proto" /> | |||
| </ItemGroup>--> | |||
| <ItemGroup> | |||
| <PackageReference Include="Google.Protobuf" Version="3.21.9" /> | |||
| <PackageReference Include="Google.Protobuf.Tools" Version="3.21.9" /> | |||
| <PackageReference Include="Grpc" Version="2.46.5" /> | |||
| <PackageReference Include="Grpc.Core" Version="2.46.5" /> | |||
| <PackageReference Include="Grpc.Tools" Version="2.50.0"> | |||
| <PrivateAssets>all</PrivateAssets> | |||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | |||
| </PackageReference> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Protobuf Include="Message2Clients.proto" /> | |||
| <Protobuf Include="Message2Server.proto" /> | |||
| <Protobuf Include="MessageType.proto" /> | |||
| <Protobuf Include="Services.proto" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -17,11 +17,10 @@ service AvailableService | |||
| rpc UseProp(IDMsg) returns (BoolRes); | |||
| rpc UseSkill(IDMsg) returns (BoolRes); | |||
| rpc SendMessage(SendMsg) returns (BoolRes); | |||
| rpc HaveMessage(IDMsg) returns (BoolRes); | |||
| rpc GetMessage(IDMsg) returns (MsgRes); | |||
| rpc GetMessage(IDMsg) returns (stream MsgRes); | |||
| rpc StartFixMachine(IDMsg) returns (BoolRes); // 开始修理机器 | |||
| rpc EndFixMachine(IDMsg) returns (BoolRes); // 主动停止修复 | |||
| rpc SaveHuman(IDMsg) returns (BoolRes); // 开始救人 | |||
| rpc StartSaveHuman(IDMsg) returns (BoolRes); // 开始救人 | |||
| rpc EndSaveHuman(IDMsg) returns (BoolRes); // 主动停止救人 | |||
| rpc Attack (AttackMsg) returns (BoolRes); | |||
| rpc CarryHuman (IDMsg) returns (BoolRes); | |||
| @@ -1,7 +1,10 @@ | |||
| for i in {1..10} | |||
| SHELL_FOLDER=$(dirname $(readlink -f "$0")) | |||
| cd $SHELL_FOLDER | |||
| cd ../.. | |||
| for i in {1..3} | |||
| do | |||
| find . -iname "*.cs" \ | |||
| -or -iname "*.c" \ | |||
| find . -iname "*.c" \ | |||
| -or -iname "*.h" \ | |||
| -or -iname "*.C" \ | |||
| -or -iname "*.H" \ | |||
| @@ -19,3 +22,10 @@ find . -iname "*.cs" \ | |||
| -or -iname "*.i++" \ | |||
| | xargs clang-format -i | |||
| done | |||
| cd logic && dotnet format && cd .. | |||
| cd installer && dotnet format && cd .. | |||
| cd launcher && dotnet format && cd .. | |||
| cd playback && dotnet format && cd .. | |||
| echo "Done!" | |||
| @@ -1,6 +1,6 @@ | |||
| using System.Windows; | |||
| [assembly:ThemeInfo( | |||
| [assembly: ThemeInfo( | |||
| ResourceDictionaryLocation.None, // where theme specific resource dictionaries are located | |||
| //(used if a resource is not found in the page, | |||
| // or application resource dictionaries) | |||
| @@ -9,7 +9,8 @@ | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> | |||
| <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" /> | |||
| <PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> | |||
| <PackageReference Include="Tencent.QCloud.Cos.Sdk" Version="5.4.32" /> | |||
| </ItemGroup> | |||
| @@ -9,21 +9,39 @@ | |||
| <Grid> | |||
| <Grid.ColumnDefinitions> | |||
| <ColumnDefinition Width="40" /> | |||
| <ColumnDefinition Width="400" /> | |||
| <ColumnDefinition Width="75" /> | |||
| <ColumnDefinition Width="75" /> | |||
| <ColumnDefinition Width="*"/> | |||
| <ColumnDefinition Width="250" /> | |||
| <ColumnDefinition Width="75" /> | |||
| <ColumnDefinition Width="75" /> | |||
| <ColumnDefinition Width="*" /> | |||
| <ColumnDefinition Width="40" /> | |||
| </Grid.ColumnDefinitions> | |||
| <Grid.RowDefinitions> | |||
| <RowDefinition Height="20" /> | |||
| <RowDefinition Height="20" /> | |||
| <RowDefinition Height="20" /> | |||
| <RowDefinition Height="20" /> | |||
| <RowDefinition Height="20" /> | |||
| <RowDefinition Height="20" /> | |||
| <RowDefinition Height="20" /> | |||
| <RowDefinition Height="20" /> | |||
| <RowDefinition Height="*" /> | |||
| <RowDefinition Height="20" /> | |||
| </Grid.RowDefinitions> | |||
| <TextBlock Grid.Row="1" Grid.Column="1" Text="将主体程序安装在:" /> | |||
| <TextBox Grid.Row="2" Grid.Column="1" Name="RouteTxtBox" Text="{Binding Route}" IsEnabled="{Binding CanEditRoute}" /> | |||
| <Button Grid.Row="2" Grid.Column="2" Name="GetRouteBtn" Content="Browse..." Command="{Binding ClickBrowseCommand}" IsEnabled="{Binding CanEditRoute}" /> | |||
| <Button Grid.Row="2" Grid.Column="3" Name="SetBtm" Content="Confirm" Command="{Binding ClickConfirmCommand}" /> | |||
| <TextBlock Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3" Text="欢迎使用选手包" Visibility="{Binding InstIntroVis}"/> | |||
| <TextBlock Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3" Text="你已经安装了选手包,请选择你要进行的操作" Visibility="{Binding EditIntroVis}"/> | |||
| <TextBlock Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3" Text="将主体程序安装在:" Visibility="{Binding InstIntroVis}"/> | |||
| <TextBlock Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3" Text="将主体程序移动到:" Visibility="{Binding MoveIntroVis}"/> | |||
| <TextBox Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="3" Name="RouteTxtBox" Text="{Binding Route}" Visibility="{Binding RouteBoxVis}"/> | |||
| <Button Grid.Row="3" Grid.Column="4" Name="GetRouteBtn" Content="Browse..." Command="{Binding ClickBrowseCommand}" Visibility="{Binding RouteBoxVis}" /> | |||
| <Button Grid.Row="3" Grid.Column="5" Name="SetBtm" Content="Confirm" Command="{Binding ClickConfirmCommand}" Visibility="{Binding RouteBoxVis}"/> | |||
| <Button Grid.Row="3" Grid.Column="2" Name="UpdateBtn" Content="Update" Command="{Binding ClickUpdateCommand}" Visibility="{Binding EditIntroVis}" /> | |||
| <Button Grid.Row="5" Grid.Column="2" Name="MoveBtn" Content="Move" Command="{Binding ClickMoveCommand}" Visibility="{Binding EditIntroVis}" /> | |||
| <Button Grid.Row="7" Grid.Column="2" Name="UninstBtn" Content="UnInst" Command="{Binding ClickUninstCommand}" Visibility="{Binding EditIntroVis}" /> | |||
| </Grid> | |||
| </Window> | |||
| @@ -9,6 +9,16 @@ using System.IO; | |||
| using System.Security.Cryptography; | |||
| using System.Text; | |||
| using System; | |||
| using COSXML.Model.Bucket; | |||
| using System.Runtime.InteropServices; | |||
| using System.Text.Json.Nodes; | |||
| using System.Net.Http.Json; | |||
| using System.Text.Json; | |||
| using System.Xml.Schema; | |||
| using static Downloader.Program; | |||
| using System.Threading.Tasks; | |||
| using System.Net.Http; | |||
| using System.Windows; | |||
| namespace starter.viewmodel.settings | |||
| { | |||
| @@ -17,28 +27,71 @@ namespace starter.viewmodel.settings | |||
| /// </summary> | |||
| public class SettingsModel | |||
| { | |||
| /// <summary> | |||
| /// downloader function | |||
| /// </summary> | |||
| private Downloader.Program.Data configData = new Downloader.Program.Data(""); | |||
| private Downloader.Program.Tencent_cos_download cloud = new Downloader.Program.Tencent_cos_download(); | |||
| /// <summary> | |||
| /// save settings | |||
| /// </summary> | |||
| public void install() | |||
| public bool install() | |||
| { | |||
| if (Downloader.Program.Tencent_cos_download.CheckAlreadyDownload()) | |||
| { | |||
| MessageBoxResult repeatOption = MessageBox.Show($"文件已存在于{Downloader.Program.Data.FilePath},是否移动到新位置?", "重复安装", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel); | |||
| //ask if abort install, with warning sign, defalut no; | |||
| if (repeatOption == MessageBoxResult.Cancel) | |||
| { | |||
| return false; //回到选择地址界面 | |||
| } | |||
| else if (repeatOption == MessageBoxResult.No) | |||
| { | |||
| System.Environment.Exit(0); | |||
| return false; | |||
| } | |||
| else | |||
| { | |||
| Downloader.Program.Tencent_cos_download.MoveProgram(Route); | |||
| return true; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| Downloader.Program.Data.ResetFilepath(Route); | |||
| Downloader.Program.Tencent_cos_download.DownloadAll(); | |||
| return true; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Route of files | |||
| /// </summary> | |||
| public string Route { | |||
| get; set; } | |||
| public string Route | |||
| { | |||
| get | |||
| { | |||
| return Downloader.Program.Data.FilePath; | |||
| } | |||
| set | |||
| { | |||
| Downloader.Program.Data.FilePath = value; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// if the route was set or is under editing | |||
| /// </summary> | |||
| public bool HaveRoute { | |||
| get; set; } | |||
| public bool EditingRoute { | |||
| get; set; } | |||
| /// <summary> | |||
| /// downloader function | |||
| public bool EditingRoute | |||
| { | |||
| get; set; | |||
| } | |||
| ///<summary> | |||
| ///if already installed | |||
| /// </summary> | |||
| private Downloader.Program downloader = new Downloader.Program(); | |||
| public bool installed | |||
| { | |||
| get; set; | |||
| } | |||
| } | |||
| } | |||
| namespace Downloader | |||
| @@ -144,7 +197,8 @@ namespace Downloader | |||
| GetObjectRequest request = new GetObjectRequest(bucket, key, localDir, localFileName); | |||
| Dictionary<string, string> test = request.GetRequestHeaders(); | |||
| request.SetCosProgressCallback(delegate(long completed, long total) { | |||
| request.SetCosProgressCallback(delegate (long completed, long total) | |||
| { | |||
| Console.WriteLine(String.Format("progress = {0:##.##}%", completed * 100.0 / total)); | |||
| }); | |||
| // 执行请求 | |||
| @@ -556,9 +610,8 @@ namespace Downloader | |||
| File.WriteAllText(@System.IO.Path.Combine(Data.FilePath, "hash.json"), Contentjson); | |||
| } | |||
| public static void MoveProgram() | |||
| public static void MoveProgram(string newPath) | |||
| { | |||
| string newPath = Console.ReadLine(); | |||
| DirectoryInfo newdi = new DirectoryInfo(newPath); | |||
| DirectoryInfo olddi = new DirectoryInfo(Data.FilePath); | |||
| try | |||
| @@ -601,8 +654,10 @@ namespace Downloader | |||
| Data.ResetFilepath(newPath); | |||
| Console.WriteLine("更改路径成功!"); | |||
| } | |||
| public static void main(string[] args) | |||
| public static async Task main(string[] args) | |||
| { | |||
| var client = new HttpClient(); | |||
| var web = new WebConnect.Web(); | |||
| Data date = new Data(""); | |||
| while (true) | |||
| { | |||
| @@ -670,7 +725,22 @@ namespace Downloader | |||
| } | |||
| else if (choose == "6") | |||
| { | |||
| MoveProgram(); | |||
| string newPath; | |||
| newPath = Console.ReadLine(); | |||
| MoveProgram(newPath); | |||
| } | |||
| else if (choose == "7") | |||
| { | |||
| Console.WriteLine("请输入email:"); | |||
| string username = Console.ReadLine(); | |||
| Console.WriteLine("请输入密码:"); | |||
| string password = Console.ReadLine(); | |||
| await web.LoginToEEsast(client, username, password); | |||
| } | |||
| else if (choose == "8") | |||
| { | |||
| await web.UserDetails(client); | |||
| } | |||
| else if (choose == "exit") | |||
| { | |||
| @@ -680,4 +750,158 @@ namespace Downloader | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| namespace WebConnect | |||
| { | |||
| class Web | |||
| { | |||
| public static string logintoken = ""; | |||
| async public Task LoginToEEsast(HttpClient client, string useremail, string password) | |||
| { | |||
| string token = ""; | |||
| using (var response = await client.PostAsync("https://api.eesast.com/users/login", JsonContent.Create(new | |||
| { | |||
| email = useremail, | |||
| password = password, | |||
| }))) | |||
| { | |||
| switch (response.StatusCode) | |||
| { | |||
| case System.Net.HttpStatusCode.OK: | |||
| Console.WriteLine("Success login"); | |||
| token = (System.Text.Json.JsonSerializer.Deserialize(await response.Content.ReadAsStreamAsync(), typeof(LoginResponse), new JsonSerializerOptions() | |||
| { | |||
| PropertyNamingPolicy = JsonNamingPolicy.CamelCase, | |||
| }) as LoginResponse)?.Token ?? throw new Exception("no token!"); | |||
| logintoken = token; | |||
| SaveToken(); | |||
| break; | |||
| default: | |||
| int code = ((int)response.StatusCode); | |||
| Console.WriteLine(code); | |||
| if (code == 401) | |||
| { | |||
| Console.WriteLine("邮箱或密码错误!"); | |||
| } | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| async public Task UserDetails(HttpClient client) //用来测试访问网站 | |||
| { | |||
| if (!ReadToken()) //读取token失败 | |||
| { | |||
| return; | |||
| } | |||
| try | |||
| { | |||
| client.DefaultRequestHeaders.Authorization = new("Bearer", logintoken); | |||
| Console.WriteLine(logintoken); | |||
| using (var response = await client.GetAsync("https://api.eesast.com/application/info")) //JsonContent.Create(new | |||
| //{ | |||
| //}))) | |||
| { | |||
| switch (response.StatusCode) | |||
| { | |||
| case System.Net.HttpStatusCode.OK: | |||
| Console.WriteLine("Require OK"); | |||
| Console.WriteLine(await response.Content.ReadAsStringAsync()); | |||
| break; | |||
| default: | |||
| int code = ((int)response.StatusCode); | |||
| if (code == 401) | |||
| { | |||
| Console.WriteLine("您未登录或登录过期,请先登录"); | |||
| } | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| catch | |||
| { | |||
| Console.WriteLine("请求错误!请检查网络连接!"); | |||
| } | |||
| } | |||
| public void SaveToken()//保存token | |||
| { | |||
| string savepath = Path.Combine(Data.dataPath, "Token.dat"); | |||
| try | |||
| { | |||
| FileStream fs = new FileStream(savepath, FileMode.OpenOrCreate, FileAccess.ReadWrite); | |||
| StreamWriter sw = new StreamWriter(fs); | |||
| fs.SetLength(0); | |||
| sw.Write(logintoken); //将token写入文件 | |||
| sw.Close(); | |||
| fs.Close(); | |||
| } | |||
| catch (DirectoryNotFoundException) | |||
| { | |||
| Console.WriteLine("保存token时未找到下载器地址!请检查下载器是否被移动!"); | |||
| } | |||
| catch (PathTooLongException) | |||
| { | |||
| Console.WriteLine("下载器的路径名太长!请尝试移动下载器!"); | |||
| } | |||
| catch (ArgumentNullException) | |||
| { | |||
| Console.WriteLine("下载器路径初始化失败!"); | |||
| } | |||
| catch (IOException) | |||
| { | |||
| Console.WriteLine("写入token.dat发生冲突!请检查token.dat是否被其它程序占用!"); | |||
| } | |||
| } | |||
| public bool ReadToken()//读取token | |||
| { | |||
| try | |||
| { | |||
| string savepath = Path.Combine(Data.dataPath, "Token.dat"); | |||
| FileStream fs = new FileStream(savepath, FileMode.Open, FileAccess.Read); | |||
| StreamReader sr = new StreamReader(fs); | |||
| logintoken = sr.ReadLine(); | |||
| sr.Close(); | |||
| fs.Close(); | |||
| return true; | |||
| } | |||
| catch (DirectoryNotFoundException) | |||
| { | |||
| Console.WriteLine("读取token时未找到下载器地址!请检查下载器是否被移动!"); | |||
| return false; | |||
| } | |||
| catch (FileNotFoundException) | |||
| { | |||
| //没有登陆 | |||
| Console.WriteLine("请先登陆!"); | |||
| return false; | |||
| } | |||
| catch (PathTooLongException) | |||
| { | |||
| Console.WriteLine("下载器的路径名太长!请尝试移动下载器!"); | |||
| return false; | |||
| } | |||
| catch (ArgumentNullException) | |||
| { | |||
| Console.WriteLine("下载器路径初始化失败!"); | |||
| return false; | |||
| } | |||
| catch (IOException) | |||
| { | |||
| Console.WriteLine("写入token.dat发生冲突!请检查token.dat是否被其它程序占用!"); | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
| [Serializable] | |||
| record LoginResponse | |||
| { | |||
| // Map `Token` to `token` when serializing | |||
| public string Token { get; set; } = ""; | |||
| } | |||
| } | |||
| @@ -1,6 +1,7 @@ | |||
| | |||
| using starter.viewmodel.common; | |||
| using System; | |||
| using System.Windows; | |||
| using System.Windows.Forms; | |||
| namespace starter.viewmodel.settings | |||
| @@ -16,37 +17,98 @@ namespace starter.viewmodel.settings | |||
| /// </summary> | |||
| public SettingsViewModel() | |||
| { | |||
| Route = Environment.GetEnvironmentVariable("USERPROFILE") + "\\THUAI6"; | |||
| CanEditRoute = true; | |||
| if (Downloader.Program.Tencent_cos_download.CheckAlreadyDownload()) | |||
| { | |||
| Installed = true; | |||
| } | |||
| else | |||
| { | |||
| Route = Environment.GetEnvironmentVariable("USERPROFILE") + "\\THUAI6"; | |||
| EditingRoute = true; | |||
| } | |||
| } | |||
| public string Route | |||
| { | |||
| get { | |||
| get | |||
| { | |||
| return obj.Route; | |||
| } | |||
| set { | |||
| set | |||
| { | |||
| obj.Route = value; | |||
| this.RaisePropertyChanged("Route"); | |||
| } | |||
| } | |||
| public bool CanEditRoute // if the user can still edit install route | |||
| public bool Installed | |||
| { | |||
| get { | |||
| return !obj.HaveRoute; | |||
| get | |||
| { | |||
| return obj.installed; | |||
| } | |||
| set { | |||
| obj.HaveRoute = !value; | |||
| set | |||
| { | |||
| obj.installed = value; | |||
| this.RaisePropertyChanged("Installed"); | |||
| this.RaisePropertyChanged("InstIntroVis"); | |||
| this.RaisePropertyChanged("EditIntroVis"); | |||
| this.RaisePropertyChanged("MoveIntroVis"); | |||
| } | |||
| } | |||
| public bool EditingRoute | |||
| { | |||
| get | |||
| { | |||
| return obj.EditingRoute; | |||
| } | |||
| set | |||
| { | |||
| obj.EditingRoute = value; | |||
| this.RaisePropertyChanged("CanEditRoute"); | |||
| this.RaisePropertyChanged("EditingRoute"); | |||
| this.RaisePropertyChanged("MoveIntroVis"); | |||
| this.RaisePropertyChanged("RouteBoxVis"); | |||
| } | |||
| } | |||
| public Visibility RouteBoxVis //if the route editing textbox is visible | |||
| { | |||
| get | |||
| { | |||
| return obj.EditingRoute ? Visibility.Visible : Visibility.Collapsed; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// if the install/edit instruction can be seen | |||
| /// </summary> | |||
| public Visibility InstIntroVis | |||
| { | |||
| get | |||
| { | |||
| return obj.installed ? Visibility.Collapsed : Visibility.Visible; | |||
| } | |||
| } | |||
| public Visibility EditIntroVis | |||
| { | |||
| get | |||
| { | |||
| return obj.installed ? Visibility.Visible : Visibility.Collapsed; | |||
| } | |||
| } | |||
| public Visibility MoveIntroVis | |||
| { | |||
| get | |||
| { | |||
| if (obj.installed == true && obj.EditingRoute == true) | |||
| return Visibility.Visible; | |||
| else | |||
| return Visibility.Collapsed; | |||
| } | |||
| } | |||
| private BaseCommand clickBrowseCommand; | |||
| public BaseCommand ClickBrowseCommand | |||
| { | |||
| get { | |||
| get | |||
| { | |||
| if (clickBrowseCommand == null) | |||
| { | |||
| clickBrowseCommand = new BaseCommand(new Action<object>(o => | |||
| @@ -54,28 +116,32 @@ namespace starter.viewmodel.settings | |||
| using (FolderBrowserDialog dialog = new FolderBrowserDialog()) | |||
| { | |||
| _ = dialog.ShowDialog(); | |||
| if (dialog.SelectedPath != String.Empty) | |||
| Route = dialog.SelectedPath; | |||
| } | |||
| })); | |||
| if (dialog.SelectedPath != String.Empty) | |||
| Route = dialog.SelectedPath; | |||
| } | |||
| })); | |||
| } | |||
| return clickBrowseCommand; | |||
| } | |||
| } | |||
| private BaseCommand clickConfirmCommand; | |||
| public BaseCommand ClickConfirmCommand | |||
| { | |||
| get { | |||
| if (clickConfirmCommand == null) | |||
| return clickBrowseCommand; | |||
| } | |||
| } | |||
| private BaseCommand clickConfirmCommand; | |||
| public BaseCommand ClickConfirmCommand | |||
| { | |||
| get | |||
| { | |||
| if (clickConfirmCommand == null) | |||
| { | |||
| clickConfirmCommand = new BaseCommand(new Action<object>(o => | |||
| { | |||
| CanEditRoute = false; | |||
| obj.install(); | |||
| })); | |||
| } | |||
| if (obj.install()) | |||
| { | |||
| EditingRoute = false; | |||
| Installed = true; | |||
| } | |||
| })); | |||
| } | |||
| return clickConfirmCommand; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| using System.Windows; | |||
| [assembly:ThemeInfo( | |||
| [assembly: ThemeInfo( | |||
| ResourceDictionaryLocation.None, // where theme specific resource dictionaries are located | |||
| //(used if a resource is not found in the page, | |||
| // or application resource dictionaries) | |||
| @@ -0,0 +1,20 @@ | |||
| <Project Sdk="Microsoft.NET.Sdk"> | |||
| <PropertyGroup> | |||
| <OutputType>Exe</OutputType> | |||
| <TargetFramework>net6.0</TargetFramework> | |||
| <ImplicitUsings>enable</ImplicitUsings> | |||
| <Nullable>enable</Nullable> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="Google.Protobuf" Version="3.21.9" /> | |||
| <PackageReference Include="Grpc" Version="2.46.5" /> | |||
| <PackageReference Include="Grpc.Core" Version="2.46.5" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <ProjectReference Include="..\..\dependency\proto\Protos.csproj" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -0,0 +1,36 @@ | |||
| using Grpc.Core; | |||
| using Protobuf; | |||
| namespace ClientTest | |||
| { | |||
| public class Program | |||
| { | |||
| public static async Task Main(string[] args) | |||
| { | |||
| Channel channel = new Channel("0.0.0.0:8888", ChannelCredentials.Insecure); | |||
| var client = new AvailableService.AvailableServiceClient(channel); | |||
| PlayerMsg playerInfo = new(); | |||
| playerInfo.PlayerId = Convert.ToInt32(args[0]); | |||
| playerInfo.PlayerType = (PlayerType)Convert.ToInt32(args[1]); | |||
| var call = client.AddPlayer(playerInfo); | |||
| while (await call.ResponseStream.MoveNext()) | |||
| { | |||
| var currentGameInfo = call.ResponseStream.Current; | |||
| if (playerInfo.PlayerType == PlayerType.HumanPlayer) | |||
| { | |||
| for (int i = 0; i < currentGameInfo.HumanMessage.Count; i++) | |||
| { | |||
| Console.WriteLine($"Human is at ({currentGameInfo.HumanMessage[i].X}, {currentGameInfo.HumanMessage[i].Y})"); | |||
| } | |||
| } | |||
| if (playerInfo.PlayerType == PlayerType.ButcherPlayer) | |||
| { | |||
| for (int i = 0; i < currentGameInfo.ButcherMessage.Count; i++) | |||
| { | |||
| Console.WriteLine($"Butcher is at ({currentGameInfo.ButcherMessage[i].X}, {currentGameInfo.ButcherMessage[i].Y})"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,68 @@ | |||
| using System.Collections.Generic; | |||
| namespace GameClass.GameObj | |||
| { | |||
| public class Team | |||
| { | |||
| private static long currentMaxTeamID = 0; | |||
| public static long CurrentMaxTeamID => currentMaxTeamID; | |||
| private readonly long teamID; | |||
| public long TeamID => teamID; | |||
| public const long invalidTeamID = long.MaxValue; | |||
| public const long noneTeamID = long.MinValue; | |||
| private readonly List<Character> playerList; | |||
| public int Score | |||
| { | |||
| get { | |||
| int score = 0; | |||
| foreach (var player in playerList) | |||
| score += player.Score; | |||
| return score; | |||
| } | |||
| } | |||
| public Character? GetPlayer(long ID) | |||
| { | |||
| foreach (Character player in playerList) | |||
| { | |||
| if (player.ID == ID) | |||
| { | |||
| return player; | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| public void AddPlayer(Character player) | |||
| { | |||
| playerList.Add(player); | |||
| } | |||
| public void OutPlayer(long ID) | |||
| { | |||
| int i; | |||
| for (i = 0; i < playerList.Count; ++i) | |||
| { | |||
| if (playerList[i].ID == ID) | |||
| break; | |||
| } | |||
| playerList.RemoveAt(i); | |||
| } | |||
| public long[] GetPlayerIDs() | |||
| { | |||
| long[] playerIDs = new long[playerList.Count]; | |||
| int num = 0; | |||
| foreach (Character player in playerList) | |||
| { | |||
| playerIDs[num++] = player.ID; | |||
| } | |||
| return playerIDs; | |||
| } | |||
| public static bool teamExists(long findTeamID) | |||
| { | |||
| return findTeamID < currentMaxTeamID; | |||
| } | |||
| public Team() | |||
| { | |||
| teamID = currentMaxTeamID++; | |||
| playerList = new List<Character>(); | |||
| } | |||
| } | |||
| } | |||
| @@ -17,7 +17,7 @@ namespace GameEngine | |||
| /// <returns>和它碰撞的物体</returns> | |||
| public IGameObj? CheckCollision(IMoveable obj, XY moveVec) | |||
| { | |||
| XY nextPos = obj.Position + XY.VectorToXY(moveVec); | |||
| XY nextPos = obj.Position + moveVec; | |||
| if (!obj.IsRigid) | |||
| { | |||
| if (gameMap.IsOutOfBound(obj)) | |||
| @@ -156,7 +156,7 @@ namespace GameEngine | |||
| { | |||
| double tmp = mod - obj.Radius - listObj.Radius; | |||
| // 计算能走的最长距离,好像这么算有一点误差? | |||
| tmp = tmp / Math.Cos(Math.Atan2(orgDeltaY, orgDeltaX) - moveVec.angle); | |||
| tmp = tmp / Math.Cos(Math.Atan2(orgDeltaY, orgDeltaX) - moveVec.Angle()); | |||
| if (tmp < 0 || tmp > uint.MaxValue || tmp == double.NaN) | |||
| { | |||
| tmpMax = uint.MaxValue; | |||
| @@ -177,11 +177,11 @@ namespace GameEngine | |||
| else | |||
| { | |||
| // 二分查找最大可能移动距离 | |||
| int left = 0, right = (int)moveVec.length; | |||
| int left = 0, right = (int)moveVec.Length(); | |||
| while (left < right - 1) | |||
| { | |||
| int mid = (right - left) / 2 + left; | |||
| if (obj.WillCollideWith(listObj, obj.Position + new XY((int)(mid * Math.Cos(moveVec.angle)), (int)(mid * Math.Sin(moveVec.angle))))) | |||
| if (obj.WillCollideWith(listObj, obj.Position + new XY((int)(mid * Math.Cos(moveVec.Angle())), (int)(mid * Math.Sin(moveVec.Angle()))))) | |||
| { | |||
| right = mid; | |||
| } | |||
| @@ -50,10 +50,10 @@ namespace GameEngine | |||
| { | |||
| /*由于四周是墙,所以人物永远不可能与越界方块碰撞*/ | |||
| XY nextPos = obj.Position + XY.VectorToXY(moveVec); | |||
| XY nextPos = obj.Position + moveVec; | |||
| double maxLen = collisionChecker.FindMax(obj, nextPos, moveVec); | |||
| maxLen = Math.Min(maxLen, obj.MoveSpeed / GameData.numOfStepPerSecond); | |||
| _ = obj.Move(new Vector(moveVec.angle, maxLen)); | |||
| _ = obj.Move(new XY(moveVec.Angle(), maxLen)); | |||
| } | |||
| public void MoveObj(IMoveable obj, int moveTime, double direction) | |||
| @@ -62,33 +62,33 @@ namespace GameEngine | |||
| return; | |||
| new Thread | |||
| ( | |||
| ()=> | |||
| () => | |||
| { | |||
| if (!obj.IsAvailable&&gameTimer.IsGaming) //不能动就直接return,后面都是能动的情况 | |||
| return; | |||
| return; | |||
| lock (obj.MoveLock) | |||
| obj.IsMoving = true; | |||
| XY moveVec = new(direction, 0.0); | |||
| double deltaLen = moveVec.length - Math.Sqrt(obj.Move(moveVec)); // 转向,并用deltaLen存储行走的误差 | |||
| double moveVecLength = 0.0; | |||
| double deltaLen = moveVecLength - Math.Sqrt(obj.Move(new XY(direction, moveVecLength))); // 转向,并用deltaLen存储行走的误差 | |||
| IGameObj? collisionObj = null; | |||
| bool isDestroyed = false; | |||
| new FrameRateTaskExecutor<int>( | |||
| () => gameTimer.IsGaming && obj.CanMove && !obj.IsResetting, | |||
| () => | |||
| { | |||
| moveVec.length = obj.MoveSpeed / GameData.numOfStepPerSecond; | |||
| moveVecLength = obj.MoveSpeed / GameData.numOfStepPerSecond; | |||
| // 越界情况处理:如果越界,则与越界方块碰撞 | |||
| bool flag; // 循环标志 | |||
| do | |||
| { | |||
| flag = false; | |||
| collisionObj = collisionChecker.CheckCollision(obj, moveVec); | |||
| collisionObj = collisionChecker.CheckCollision(obj, new XY(direction, moveVecLength)); | |||
| if (collisionObj == null) | |||
| break; | |||
| switch (OnCollision(obj, collisionObj, moveVec)) | |||
| switch (OnCollision(obj, collisionObj, new XY(direction, moveVecLength))) | |||
| { | |||
| case AfterCollision.ContinueCheck: | |||
| flag = true; | |||
| @@ -98,13 +98,13 @@ namespace GameEngine | |||
| isDestroyed = true; | |||
| return false; | |||
| case AfterCollision.MoveMax: | |||
| MoveMax(obj, moveVec); | |||
| moveVec.length = 0; | |||
| MoveMax(obj, new XY(direction, moveVecLength)); | |||
| moveVecLength = 0; | |||
| break; | |||
| } | |||
| } while (flag); | |||
| deltaLen += moveVec.length - Math.Sqrt(obj.Move(moveVec)); | |||
| deltaLen += moveVecLength - Math.Sqrt(obj.Move(new XY(direction, moveVecLength))); | |||
| return true; | |||
| }, | |||
| @@ -118,14 +118,14 @@ namespace GameEngine | |||
| flag = false; | |||
| if (!isDestroyed) | |||
| { | |||
| moveVec.length = deltaLen + leftTime * obj.MoveSpeed / GameData.numOfPosGridPerCell; | |||
| if ((collisionObj = collisionChecker.CheckCollision(obj, moveVec)) == null) | |||
| moveVecLength = deltaLen + leftTime * obj.MoveSpeed / GameData.numOfPosGridPerCell; | |||
| if ((collisionObj = collisionChecker.CheckCollision(obj, new XY(direction, moveVecLength))) == null) | |||
| { | |||
| obj.Move(moveVec); | |||
| obj.Move(new XY(direction, moveVecLength)); | |||
| } | |||
| else | |||
| { | |||
| switch (OnCollision(obj, collisionObj, moveVec)) | |||
| switch (OnCollision(obj, collisionObj, new XY(direction, moveVecLength))) | |||
| { | |||
| case AfterCollision.ContinueCheck: | |||
| flag = true; | |||
| @@ -135,8 +135,8 @@ namespace GameEngine | |||
| isDestroyed = true; | |||
| break; | |||
| case AfterCollision.MoveMax: | |||
| MoveMax(obj, moveVec); | |||
| moveVec.length = 0; | |||
| MoveMax(obj, new XY(direction, moveVecLength)); | |||
| moveVecLength = 0; | |||
| break; | |||
| } | |||
| } | |||
| @@ -0,0 +1,66 @@ | |||
| using System; | |||
| using GameClass.GameObj; | |||
| using GameEngine; | |||
| using Preparation.Utility; | |||
| namespace Gaming | |||
| { | |||
| public partial class Game | |||
| { | |||
| private readonly MoveManager moveManager; | |||
| private class MoveManager | |||
| { | |||
| // 人物移动 | |||
| public void MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) | |||
| { | |||
| moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection); | |||
| } | |||
| /* | |||
| private void ActivateMine(Character player, Mine mine) | |||
| { | |||
| gameMap.ObjListLock.EnterWriteLock(); | |||
| try { gameMap.ObjList.Remove(mine); } | |||
| catch { } | |||
| finally { gameMap.ObjListLock.ExitWriteLock(); } | |||
| switch (mine.GetPropType()) | |||
| { | |||
| case PropType.Dirt: | |||
| player.AddMoveSpeed(Constant.dirtMoveSpeedDebuff, Constant.buffPropTime); | |||
| break; | |||
| case PropType.Attenuator: | |||
| player.AddAP(Constant.attenuatorAtkDebuff, Constant.buffPropTime); | |||
| break; | |||
| case PropType.Divider: | |||
| player.ChangeCD(Constant.dividerCdDiscount, Constant.buffPropTime); | |||
| break; | |||
| } | |||
| } | |||
| */ | |||
| // private readonly Map gameMap; | |||
| private readonly MoveEngine moveEngine; | |||
| public MoveManager(Map gameMap) | |||
| { | |||
| // this.gameMap = gameMap; | |||
| this.moveEngine = new MoveEngine( | |||
| gameMap: gameMap, | |||
| OnCollision: (obj, collisionObj, moveVec) => | |||
| { | |||
| //if (collisionObj is Mine) | |||
| //{ | |||
| // ActivateMine((Character)obj, (Mine)collisionObj); | |||
| // return MoveEngine.AfterCollision.ContinueCheck; | |||
| //} | |||
| return MoveEngine.AfterCollision.MoveMax; }, | |||
| EndMove: obj => | |||
| { | |||
| // Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64); | |||
| } | |||
| ); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -87,11 +87,9 @@ namespace Preparation.Utility | |||
| { | |||
| None = 0, | |||
| Player = 1, | |||
| Bullet = 2, | |||
| Prop = 3, | |||
| Gem = 4, | |||
| Map = 5, | |||
| BombedBullet = 6, | |||
| PickedProp = 7 | |||
| Prop = 2, | |||
| Map = 3, | |||
| BombedBullet = 4, | |||
| PickedProp = 5 | |||
| } | |||
| } | |||
| @@ -12,6 +12,11 @@ namespace Preparation.Utility | |||
| this.x = x; | |||
| this.y = y; | |||
| } | |||
| public XY(double angle, double length) | |||
| { | |||
| this.x = (int)(length * Math.Cos(angle)); | |||
| this.y = (int)(length * Math.Sin(angle)); | |||
| } | |||
| public override string ToString() | |||
| { | |||
| return "(" + x.ToString() + "," + y.ToString() + ")"; | |||
| @@ -32,5 +37,13 @@ namespace Preparation.Utility | |||
| { | |||
| return Math.Sqrt(((long)(p1.x - p2.x) * (p1.x - p2.x)) + ((long)(p1.y - p2.y) * (p1.y - p2.y))); | |||
| } | |||
| public double Length() | |||
| { | |||
| return Math.Sqrt(((long)x * x) + ((long)y * y)); | |||
| } | |||
| public double Angle() | |||
| { | |||
| return Math.Atan2(y, x); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,110 @@ | |||
| using Grpc.Core; | |||
| using Protobuf; | |||
| using System.Threading; | |||
| using Timothy.FrameRateTask; | |||
| using System; | |||
| using System.Net.Http.Headers; | |||
| namespace Server | |||
| { | |||
| public class Game | |||
| { | |||
| private const int gameTime = 3000; | |||
| public int GameTime => gameTime; | |||
| private MessageToClient gameInfo = new(); | |||
| private object gameInfoLock = new(); | |||
| private int isGaming = 0; | |||
| public bool IsGaming | |||
| { | |||
| get => Interlocked.CompareExchange(ref isGaming, 0, 0) != 0; | |||
| set => Interlocked.Exchange(ref isGaming, value ? 1 : 0); | |||
| } | |||
| public MessageToClient GetCopiedGameInfo() | |||
| { | |||
| lock (gameInfoLock) | |||
| { | |||
| return gameInfo.Clone(); | |||
| } | |||
| } | |||
| public void AddPlayer(PlayerMsg player) | |||
| { | |||
| lock (gameInfoLock) | |||
| { | |||
| if (player.PlayerType == PlayerType.NullPlayerType) | |||
| return; | |||
| if (player.PlayerType == PlayerType.HumanPlayer) | |||
| { | |||
| gameInfo.HumanMessage.Add(new MessageOfHuman() | |||
| { | |||
| PlayerId = player.PlayerId | |||
| }); | |||
| return; | |||
| } | |||
| if (player.PlayerType == PlayerType.ButcherPlayer) | |||
| { | |||
| gameInfo.ButcherMessage.Add(new MessageOfButcher() | |||
| { | |||
| PlayerId = player.PlayerId | |||
| }); | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| public void Move() | |||
| { | |||
| } | |||
| public SemaphoreSlim StartGame() | |||
| { | |||
| IsGaming = true; | |||
| var waitHandle = new SemaphoreSlim(0); | |||
| new Thread | |||
| ( | |||
| () => | |||
| { | |||
| new FrameRateTaskExecutor<int> | |||
| ( | |||
| () => IsGaming, | |||
| () => | |||
| { | |||
| lock (gameInfo) | |||
| { | |||
| for (int i = 0; i < gameInfo.HumanMessage.Count; i++) | |||
| { | |||
| if (gameInfo.HumanMessage[i] != null) | |||
| { | |||
| gameInfo.HumanMessage[i].X++; | |||
| gameInfo.HumanMessage[i].Y--; | |||
| } | |||
| } | |||
| for (int i = 0; i < gameInfo.ButcherMessage.Count; i++) | |||
| { | |||
| if (gameInfo.ButcherMessage[i] != null) | |||
| { | |||
| gameInfo.ButcherMessage[i].X--; | |||
| gameInfo.ButcherMessage[i].Y++; | |||
| } | |||
| } | |||
| } | |||
| }, | |||
| 100, | |||
| () => | |||
| { | |||
| IsGaming = false; | |||
| waitHandle.Release(); | |||
| return 0; | |||
| }, | |||
| gameTime | |||
| ).Start(); | |||
| } | |||
| ) | |||
| { IsBackground = true }.Start(); | |||
| return waitHandle; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,121 @@ | |||
| using Grpc.Core; | |||
| using Protobuf; | |||
| using System.Threading; | |||
| using Timothy.FrameRateTask; | |||
| using System; | |||
| using System.Net.Http.Headers; | |||
| namespace Server | |||
| { | |||
| public class GameServer : AvailableService.AvailableServiceBase | |||
| { | |||
| private Dictionary<long, (SemaphoreSlim, SemaphoreSlim)> semaDict = new(); | |||
| private object gameLock = new(); | |||
| private const int playerNum = 1; | |||
| private MessageToClient currentGameInfo = new(); | |||
| private Game game = new(); | |||
| public int GameTime => game.GameTime; | |||
| private SemaphoreSlim endGameSem = new(0); | |||
| public override Task<BoolRes> TryConnection(IDMsg request, ServerCallContext context) | |||
| { | |||
| var onConnection = new BoolRes(); | |||
| lock (gameLock) | |||
| { | |||
| // if (0 <= request.PlayerId && request.PlayerId < playerNum) | |||
| { | |||
| onConnection.ActSuccess = true; | |||
| Console.WriteLine(onConnection.ActSuccess); | |||
| return Task.FromResult(onConnection); | |||
| } | |||
| } | |||
| onConnection.ActSuccess = false; | |||
| return Task.FromResult(onConnection); | |||
| } | |||
| public override async Task AddPlayer(PlayerMsg request, IServerStreamWriter<MessageToClient> responseStream, ServerCallContext context) | |||
| { | |||
| lock (gameLock) | |||
| { | |||
| if (game.IsGaming) | |||
| return; | |||
| game.AddPlayer(request); | |||
| var temp = (new SemaphoreSlim(0, 1), new SemaphoreSlim(0, 1)); | |||
| bool start = false; | |||
| Console.WriteLine($"Id: {request.PlayerId} joins."); | |||
| lock (semaDict) | |||
| { | |||
| semaDict.Add(request.PlayerId, temp); | |||
| start = semaDict.Count == playerNum; | |||
| } | |||
| if (start) | |||
| { | |||
| Console.WriteLine("Game starts!"); | |||
| StartGame(); | |||
| } | |||
| } | |||
| do | |||
| { | |||
| semaDict[request.PlayerId].Item1.Wait(); | |||
| if (currentGameInfo != null) | |||
| { | |||
| await responseStream.WriteAsync(currentGameInfo); | |||
| Console.WriteLine("Send!"); | |||
| } | |||
| semaDict[request.PlayerId].Item2.Release(); | |||
| } while (game.IsGaming); | |||
| } | |||
| public void StartGame() | |||
| { | |||
| var waitHandle = game.StartGame(); | |||
| new Thread(() => | |||
| { | |||
| new FrameRateTaskExecutor<int> | |||
| ( | |||
| () => game.IsGaming, | |||
| ReportGame, | |||
| 1000, | |||
| () => | |||
| { | |||
| ReportGame(); // 最后发一次消息,唤醒发消息的线程,防止发消息的线程由于有概率处在 Wait 状态而卡住 | |||
| return 0; | |||
| } | |||
| ).Start(); | |||
| }) | |||
| { IsBackground = true }.Start(); | |||
| new Thread(() => | |||
| { | |||
| waitHandle.Wait(); | |||
| this.endGameSem.Release(); | |||
| }) | |||
| { IsBackground = true }.Start(); | |||
| } | |||
| public void WaitForEnd() | |||
| { | |||
| this.endGameSem.Wait(); | |||
| } | |||
| public void ReportGame() | |||
| { | |||
| currentGameInfo = game.GetCopiedGameInfo(); | |||
| foreach (var kvp in semaDict) | |||
| { | |||
| kvp.Value.Item1.Release(); | |||
| } | |||
| foreach (var kvp in semaDict) | |||
| { | |||
| kvp.Value.Item2.Wait(); | |||
| } | |||
| } | |||
| public GameServer() | |||
| { | |||
| } | |||
| } | |||
| } | |||
| @@ -1,2 +1,35 @@ | |||
| // See https://aka.ms/new-console-template for more information | |||
| Console.WriteLine("Hello, World!"); | |||
| using Grpc.Core; | |||
| using Protobuf; | |||
| using System.Threading; | |||
| using Timothy.FrameRateTask; | |||
| using System; | |||
| using System.Net.Http.Headers; | |||
| namespace Server | |||
| { | |||
| public class Program | |||
| { | |||
| public static void Main() | |||
| { | |||
| try | |||
| { | |||
| GameServer gameServer = new(); | |||
| Grpc.Core.Server server = new Grpc.Core.Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) | |||
| { | |||
| Services = { AvailableService.BindService(gameServer) }, | |||
| Ports = { new ServerPort("0.0.0.0", 8888, ServerCredentials.Insecure) } | |||
| }; | |||
| server.Start(); | |||
| Console.WriteLine("Server begins to listen!"); | |||
| gameServer.WaitForEnd(); | |||
| Console.WriteLine("Server end!"); | |||
| server.ShutdownAsync().Wait(); | |||
| } | |||
| catch (Exception ex) | |||
| { | |||
| Console.WriteLine(ex.ToString()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -7,4 +7,19 @@ | |||
| <Nullable>enable</Nullable> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="FrameRateTask" Version="1.1.2" /> | |||
| <PackageReference Include="Google.Protobuf" Version="3.21.9" /> | |||
| <PackageReference Include="Grpc" Version="2.46.5" /> | |||
| <PackageReference Include="Grpc.Core" Version="2.46.5" /> | |||
| <PackageReference Include="Grpc.Tools" Version="2.50.0"> | |||
| <PrivateAssets>all</PrivateAssets> | |||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | |||
| </PackageReference> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <ProjectReference Include="..\..\dependency\proto\Protos.csproj" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -0,0 +1,7 @@ | |||
| @echo off | |||
| start cmd /k .\Server\bin\Debug\net6.0\Server.exe | |||
| start cmd /k .\ClientTest\bin\Debug\net6.0\ClientTest.exe 0 1 | |||
| start cmd /k .\ClientTest\bin\Debug\net6.0\ClientTest.exe 1 2 | |||
| @@ -5,6 +5,12 @@ VisualStudioVersion = 17.0.32014.148 | |||
| MinimumVisualStudioVersion = 10.0.40219.1 | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}" | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientTest", "ClientTest\ClientTest.csproj", "{F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}" | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Protos", "..\dependency\proto\Protos.csproj", "{9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}" | |||
| EndProject | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameEngine", "GameEngine\GameEngine.csproj", "{C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}" | |||
| EndProject | |||
| Global | |||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
| Debug|Any CPU = Debug|Any CPU | |||
| @@ -15,6 +21,18 @@ Global | |||
| {D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| EndGlobalSection | |||
| GlobalSection(SolutionProperties) = preSolution | |||
| HideSolutionNode = FALSE | |||