| @@ -135,9 +135,6 @@ private: | |||||
| // 将信息加载到buffer | // 将信息加载到buffer | ||||
| void LoadBuffer(protobuf::MessageToClient&); | void LoadBuffer(protobuf::MessageToClient&); | ||||
| // 解锁状态更新线程 | |||||
| void UnBlockBuffer(); | |||||
| // 解锁AI线程 | // 解锁AI线程 | ||||
| void UnBlockAI(); | void UnBlockAI(); | ||||
| @@ -455,7 +455,7 @@ void HumanDebugAPI::PrintHuman() const | |||||
| logger->info("******Human Info******"); | logger->info("******Human Info******"); | ||||
| logger->info("playerID={}, GUID={}, x={}, y={}", human->playerID, human->guid, human->x, human->y); | logger->info("playerID={}, GUID={}, x={}, y={}", human->playerID, human->guid, human->x, human->y); | ||||
| logger->info("speed={}, view range={}, skill time={}, prop={}, place={}", human->speed, human->viewRange, human->timeUntilSkillAvailable, THUAI6::propTypeDict[human->prop], THUAI6::placeTypeDict[human->place]); | logger->info("speed={}, view range={}, skill time={}, prop={}, place={}", human->speed, human->viewRange, human->timeUntilSkillAvailable, THUAI6::propTypeDict[human->prop], THUAI6::placeTypeDict[human->place]); | ||||
| logger->info("state={}, life={}, hangedTime={}", THUAI6::humanStateDict[human->state], human->life, human->hangedTime); | |||||
| logger->info("state={}, life={}, hanged time={}", THUAI6::humanStateDict[human->state], human->life, human->hangedTime); | |||||
| std::string humanBuff = "buff="; | std::string humanBuff = "buff="; | ||||
| for (auto buff : human->buff) | for (auto buff : human->buff) | ||||
| humanBuff += THUAI6::humanBuffDict[buff] + ", "; | humanBuff += THUAI6::humanBuffDict[buff] + ", "; | ||||
| @@ -471,7 +471,7 @@ void ButcherDebugAPI::PrintHuman() const | |||||
| logger->info("******Human Info******"); | logger->info("******Human Info******"); | ||||
| logger->info("playerID={}, GUID={}, x={}, y={}", human->playerID, human->guid, human->x, human->y); | logger->info("playerID={}, GUID={}, x={}, y={}", human->playerID, human->guid, human->x, human->y); | ||||
| logger->info("speed={}, view range={}, skill time={}, prop={}, place={}", human->speed, human->viewRange, human->timeUntilSkillAvailable, THUAI6::propTypeDict[human->prop], THUAI6::placeTypeDict[human->place]); | logger->info("speed={}, view range={}, skill time={}, prop={}, place={}", human->speed, human->viewRange, human->timeUntilSkillAvailable, THUAI6::propTypeDict[human->prop], THUAI6::placeTypeDict[human->place]); | ||||
| logger->info("state={}, life={}, hangedTime={}", THUAI6::humanStateDict[human->state], human->life, human->hangedTime); | |||||
| logger->info("state={}, life={}, hanged time={}", THUAI6::humanStateDict[human->state], human->life, human->hangedTime); | |||||
| std::string humanBuff = "buff="; | std::string humanBuff = "buff="; | ||||
| for (auto buff : human->buff) | for (auto buff : human->buff) | ||||
| humanBuff += THUAI6::humanBuffDict[buff] + ", "; | humanBuff += THUAI6::humanBuffDict[buff] + ", "; | ||||
| @@ -538,7 +538,7 @@ void HumanDebugAPI::PrintSelfInfo() const | |||||
| logger->info("******Self Info******"); | logger->info("******Self Info******"); | ||||
| logger->info("playerID={}, GUID={}, x={}, y={}", self->playerID, self->guid, self->x, self->y); | logger->info("playerID={}, GUID={}, x={}, y={}", self->playerID, self->guid, self->x, self->y); | ||||
| logger->info("speed={}, view range={}, skill time={}, prop={}, place={}", self->speed, self->viewRange, self->timeUntilSkillAvailable, THUAI6::propTypeDict[self->prop], THUAI6::placeTypeDict[self->place]); | logger->info("speed={}, view range={}, skill time={}, prop={}, place={}", self->speed, self->viewRange, self->timeUntilSkillAvailable, THUAI6::propTypeDict[self->prop], THUAI6::placeTypeDict[self->place]); | ||||
| logger->info("state={}, life={}, hangedTime={}", THUAI6::humanStateDict[self->state], self->life, self->hangedTime); | |||||
| logger->info("state={}, life={}, hanged time={}", THUAI6::humanStateDict[self->state], self->life, self->hangedTime); | |||||
| std::string humanBuff = "buff="; | std::string humanBuff = "buff="; | ||||
| for (auto buff : self->buff) | for (auto buff : self->buff) | ||||
| humanBuff += THUAI6::humanBuffDict[buff] + ", "; | humanBuff += THUAI6::humanBuffDict[buff] + ", "; | ||||
| @@ -263,6 +263,7 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message) | |||||
| bufferState->humanSelf = Proto2THUAI6::Protobuf2THUAI6Human(item); | bufferState->humanSelf = Proto2THUAI6::Protobuf2THUAI6Human(item); | ||||
| } | } | ||||
| bufferState->humans.push_back(Proto2THUAI6::Protobuf2THUAI6Human(item)); | bufferState->humans.push_back(Proto2THUAI6::Protobuf2THUAI6Human(item)); | ||||
| logger->debug("Add Human!"); | |||||
| } | } | ||||
| for (const auto& item : message.butcher_message()) | for (const auto& item : message.butcher_message()) | ||||
| { | { | ||||
| @@ -307,6 +308,7 @@ void Logic::LoadBuffer(protobuf::MessageToClient& message) | |||||
| bufferState->butcherSelf = Proto2THUAI6::Protobuf2THUAI6Butcher(item); | bufferState->butcherSelf = Proto2THUAI6::Protobuf2THUAI6Butcher(item); | ||||
| } | } | ||||
| bufferState->butchers.push_back(Proto2THUAI6::Protobuf2THUAI6Butcher(item)); | bufferState->butchers.push_back(Proto2THUAI6::Protobuf2THUAI6Butcher(item)); | ||||
| logger->debug("Add Butcher!"); | |||||
| } | } | ||||
| for (const auto& item : message.human_message()) | for (const auto& item : message.human_message()) | ||||
| { | { | ||||
| @@ -400,15 +402,6 @@ void Logic::UnBlockAI() | |||||
| cvAI.notify_one(); | cvAI.notify_one(); | ||||
| } | } | ||||
| void Logic::UnBlockBuffer() | |||||
| { | |||||
| { | |||||
| std::lock_guard<std::mutex> lock(mtxBuffer); | |||||
| bufferUpdated = true; | |||||
| } | |||||
| cvBuffer.notify_one(); | |||||
| } | |||||
| int Logic::GetCounter() const | int Logic::GetCounter() const | ||||
| { | { | ||||
| std::unique_lock<std::mutex> lock(mtxState); | std::unique_lock<std::mutex> lock(mtxState); | ||||
| @@ -506,7 +499,7 @@ void Logic::Main(CreateAIFunc createAI, std::string IP, std::string port, bool f | |||||
| // 连接服务器 | // 连接服务器 | ||||
| if (TryConnection()) | if (TryConnection()) | ||||
| { | { | ||||
| logger->info("Connect to the server successfully, AI thread will be start."); | |||||
| logger->info("Connect to the server successfully, AI thread will be started."); | |||||
| tAI = std::thread(AIThread); | tAI = std::thread(AIThread); | ||||
| if (tAI.joinable()) | if (tAI.joinable()) | ||||
| { | { | ||||
| @@ -1,7 +1,7 @@ | |||||
| import PyAPI.structures as THUAI6 | import PyAPI.structures as THUAI6 | ||||
| from PyAPI.Interface import ILogic, IHumanAPI, IButcherAPI, IGameTimer, IAI | from PyAPI.Interface import ILogic, IHumanAPI, IButcherAPI, IGameTimer, IAI | ||||
| from math import pi | from math import pi | ||||
| from concurrent.futures import ProcessPoolExecutor, Future | |||||
| from concurrent.futures import ThreadPoolExecutor, Future | |||||
| from typing import List, Union | from typing import List, Union | ||||
| @@ -9,7 +9,7 @@ class HumanAPI(IHumanAPI, IGameTimer): | |||||
| def __init__(self, logic: ILogic) -> None: | def __init__(self, logic: ILogic) -> None: | ||||
| self.__logic = logic | self.__logic = logic | ||||
| self.__pool = ProcessPoolExecutor(20) | |||||
| self.__pool = ThreadPoolExecutor(20) | |||||
| # 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 | # 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 | ||||
| @@ -133,7 +133,7 @@ class ButcherAPI(IButcherAPI, IGameTimer): | |||||
| def __init__(self, logic: ILogic) -> None: | def __init__(self, logic: ILogic) -> None: | ||||
| self.__logic = logic | self.__logic = logic | ||||
| self.__pool = ProcessPoolExecutor(20) | |||||
| self.__pool = ThreadPoolExecutor(20) | |||||
| # 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 | # 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 | ||||
| @@ -1,20 +1,58 @@ | |||||
| import PyAPI.structures as THUAI6 | |||||
| from PyAPI.Interface import ILogic, IHumanAPI, IButcherAPI, IGameTimer, IAI | |||||
| from math import pi | from math import pi | ||||
| from concurrent.futures import ProcessPoolExecutor, Future | |||||
| from concurrent.futures import ThreadPoolExecutor, Future | |||||
| from typing import List, Union | from typing import List, Union | ||||
| import logging | |||||
| import os | |||||
| import datetime | |||||
| import PyAPI.structures as THUAI6 | |||||
| from PyAPI.Interface import ILogic, IHumanAPI, IButcherAPI, IGameTimer, IAI | |||||
| class HumanDebugAPI(IHumanAPI, IGameTimer): | class HumanDebugAPI(IHumanAPI, IGameTimer): | ||||
| def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None: | def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None: | ||||
| self.__logic = logic | self.__logic = logic | ||||
| self.__pool = ProcessPoolExecutor(20) | |||||
| self.__pool = ThreadPoolExecutor(20) | |||||
| self.__startPoint = datetime.datetime.now() | |||||
| self.__logger = logging.getLogger("api " + str(playerID)) | |||||
| self.__logger.setLevel(logging.DEBUG) | |||||
| formatter = logging.Formatter( | |||||
| "[%(name)s] [%(asctime)s] [%(levelname)s] %(message)s", "%H:%M:%S.%e") | |||||
| # 确保文件存在 | |||||
| if not os.path.exists(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs"): | |||||
| os.makedirs(os.path.dirname(os.path.dirname( | |||||
| os.path.realpath(__file__))) + "/logs") | |||||
| fileHandler = logging.FileHandler(os.path.dirname( | |||||
| os.path.dirname(os.path.realpath(__file__))) + "/logs/api-" + str(playerID) + "-log.txt") | |||||
| screenHandler = logging.StreamHandler() | |||||
| if file: | |||||
| fileHandler.setLevel(logging.DEBUG) | |||||
| fileHandler.setFormatter(formatter) | |||||
| self.__logger.addHandler(fileHandler) | |||||
| if screen: | |||||
| if warnOnly: | |||||
| screenHandler.setLevel(logging.WARNING) | |||||
| else: | |||||
| screenHandler.setLevel(logging.INFO) | |||||
| screenHandler.setFormatter(formatter) | |||||
| self.__logger.addHandler(screenHandler) | |||||
| # 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 | # 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 | ||||
| def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]: | def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.Move, timeInMilliseconds, angle) | |||||
| self.__logger.info( | |||||
| f"Move: timeInMilliseconds = {timeInMilliseconds}, angle = {angle}, called at {self.__GetTime()}ms") | |||||
| def logMove() -> bool: | |||||
| result = self.__logic.Move(timeInMilliseconds, angle) | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"Move: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logMove) | |||||
| # 向特定方向移动 | # 向特定方向移动 | ||||
| @@ -33,28 +71,90 @@ class HumanDebugAPI(IHumanAPI, IGameTimer): | |||||
| # 道具和技能相关 | # 道具和技能相关 | ||||
| def PickProp(self, propType: THUAI6.PropType) -> Future[bool]: | def PickProp(self, propType: THUAI6.PropType) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.PickProp, propType) | |||||
| self.__logger.info( | |||||
| f"PickProp: prop = {propType.name}, called at {self.__GetTime()}ms") | |||||
| def logPick() -> bool: | |||||
| result = self.__logic.PickProp(propType) | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"PickProp: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logPick) | |||||
| def UseProp(self) -> Future[bool]: | def UseProp(self) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.UseProp) | |||||
| self.__logger.info( | |||||
| f"UseProp: called at {self.__GetTime()}ms") | |||||
| def logUse() -> bool: | |||||
| result = self.__logic.UseProp() | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"UseProp: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logUse) | |||||
| def UseSkill(self) -> Future[bool]: | def UseSkill(self) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.UseSkill) | |||||
| self.__logger.info( | |||||
| f"UseSkill: called at {self.__GetTime()}ms") | |||||
| def logUse() -> bool: | |||||
| result = self.__logic.UseSkill() | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"UseSkill: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logUse) | |||||
| # 消息相关,接收消息时无消息则返回(-1, '') | # 消息相关,接收消息时无消息则返回(-1, '') | ||||
| def SendMessage(self, toID: int, message: str) -> Future[bool]: | def SendMessage(self, toID: int, message: str) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.SendMessage, toID, message) | |||||
| self.__logger.info( | |||||
| f"SendMessage: toID = {toID}, message = {message}, called at {self.__GetTime()}ms") | |||||
| def logSend() -> bool: | |||||
| result = self.__logic.SendMessage(toID, message) | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"SendMessage: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logSend) | |||||
| def HaveMessage(self) -> Future[bool]: | def HaveMessage(self) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.HaveMessage) | |||||
| self.__logger.info( | |||||
| f"HaveMessage: called at {self.__GetTime()}ms") | |||||
| def logHave() -> bool: | |||||
| result = self.__logic.HaveMessage() | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"HaveMessage: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logHave) | |||||
| def GetMessage(self) -> Future[tuple[int, str]]: | def GetMessage(self) -> Future[tuple[int, str]]: | ||||
| return self.__pool.submit(self.__logic.GetMessage) | |||||
| self.__logger.info( | |||||
| f"GetMessage: called at {self.__GetTime()}ms") | |||||
| def logGet() -> tuple[int, str]: | |||||
| result = self.__logic.GetMessage() | |||||
| if result[0] == -1: | |||||
| self.__logger.warning( | |||||
| f"GetMessage: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logGet) | |||||
| # 等待下一帧 | # 等待下一帧 | ||||
| def Wait(self) -> Future[bool]: | def Wait(self) -> Future[bool]: | ||||
| self.__logger.info( | |||||
| f"Wait: called at {self.__GetTime()}ms") | |||||
| if self.__logic.GetCounter() == -1: | if self.__logic.GetCounter() == -1: | ||||
| return self.__pool.submit(lambda: False) | return self.__pool.submit(lambda: False) | ||||
| else: | else: | ||||
| @@ -89,56 +189,191 @@ class HumanDebugAPI(IHumanAPI, IGameTimer): | |||||
| # 用于DEBUG的输出函数,仅在DEBUG模式下有效 | # 用于DEBUG的输出函数,仅在DEBUG模式下有效 | ||||
| def PrintHuman(self) -> None: | def PrintHuman(self) -> None: | ||||
| pass | |||||
| for human in self.__logic.GetHumans(): | |||||
| self.__logger.info("******Human Info******") | |||||
| self.__logger.info( | |||||
| f"playerID={human.playerID}, GUID={human.guid}, x={human.x}, y={human.y}") | |||||
| self.__logger.info( | |||||
| f"speed={human.speed}, view range={human.viewRange}, skill time={human.timeUntilSkillAvailable}, prop={human.prop.name}, place={human.place.name}") | |||||
| self.__logger.info( | |||||
| f"state={human.state.name}, life={human.life}, hanged time={human.hangedTime}") | |||||
| self.__logger.info("buff=") | |||||
| humanBuff = "" | |||||
| for buff in human.buff: | |||||
| humanBuff += buff.name + ", " | |||||
| self.__logger.info(humanBuff) | |||||
| self.__logger.info("**********************") | |||||
| def PrintButcher(self) -> None: | def PrintButcher(self) -> None: | ||||
| pass | |||||
| for butcher in self.__logic.GetButchers(): | |||||
| self.__logger.info("******Butcher Info******") | |||||
| self.__logger.info( | |||||
| f"playerID={butcher.playerID}, GUID={butcher.guid}, x={butcher.x}, y={butcher.y}") | |||||
| self.__logger.info( | |||||
| f"speed={butcher.speed}, view range={butcher.viewRange}, skill time={butcher.timeUntilSkillAvailable}, prop={butcher.prop.name}, place={butcher.place.name}") | |||||
| self.__logger.info( | |||||
| f"damage={butcher.damage}, movable={butcher.movable}") | |||||
| self.__logger.info("buff=") | |||||
| butcherBuff = "" | |||||
| for buff in butcher.buff: | |||||
| butcherBuff += buff.name + ", " | |||||
| self.__logger.info(butcherBuff) | |||||
| self.__logger.info("************************") | |||||
| def PrintProp(self) -> None: | def PrintProp(self) -> None: | ||||
| pass | |||||
| for prop in self.__logic.GetProps(): | |||||
| self.__logger.info("******Prop Info******") | |||||
| self.__logger.info( | |||||
| f"GUID={prop.guid}, x={prop.x}, y={prop.y}, place={prop.place.name}, is moving={prop.isMoving}") | |||||
| self.__logger.info("*********************") | |||||
| def PrintSelfInfo(self) -> None: | def PrintSelfInfo(self) -> None: | ||||
| pass | |||||
| mySelf = self.__logic.GetSelfInfo() | |||||
| self.__logger.info("******Self Info******") | |||||
| self.__logger.info( | |||||
| f"playerID={mySelf.playerID}, GUID={mySelf.guid}, x={mySelf.x}, y={mySelf.y}") | |||||
| self.__logger.info( | |||||
| f"speed={mySelf.speed}, view range={mySelf.viewRange}, skill time={mySelf.timeUntilSkillAvailable}, prop={mySelf.prop.name}, place={mySelf.place.name}") | |||||
| if isinstance(mySelf, THUAI6.Human): | |||||
| self.__logger.info( | |||||
| f"state={mySelf.state.name}, life={mySelf.life}, hanged time={mySelf.hangedTime}") | |||||
| else: | |||||
| self.__logger.info( | |||||
| f"damage={mySelf.damage}, movable={mySelf.movable}") | |||||
| self.__logger.info("buff=") | |||||
| mySelfBuff = "" | |||||
| for buff in mySelf.buff: | |||||
| mySelfBuff += buff.name + ", " | |||||
| self.__logger.info(mySelfBuff) | |||||
| self.__logger.info("*********************") | |||||
| # 人类阵营的特殊函数 | # 人类阵营的特殊函数 | ||||
| def Escape(self) -> Future[bool]: | def Escape(self) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.Escape) | |||||
| self.__logger.info( | |||||
| f"Escape: called at {self.__GetTime()}ms") | |||||
| def logEscape() -> bool: | |||||
| result = self.__logic.Escape() | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"Escape: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logEscape) | |||||
| def StartFixMachine(self) -> Future[bool]: | def StartFixMachine(self) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.StartFixMachine) | |||||
| self.__logger.info( | |||||
| f"StartFixMachine: called at {self.__GetTime()}ms") | |||||
| def logStart() -> bool: | |||||
| result = self.__logic.StartFixMachine() | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"StartFixMachine: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logStart) | |||||
| def EndFixMachine(self) -> Future[bool]: | def EndFixMachine(self) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.EndFixMachine) | |||||
| self.__logger.info( | |||||
| f"EndFixMachine: called at {self.__GetTime()}ms") | |||||
| def logEnd() -> bool: | |||||
| result = self.__logic.EndFixMachine() | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"EndFixMachine: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logEnd) | |||||
| def StartSaveHuman(self) -> Future[bool]: | def StartSaveHuman(self) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.StartSaveHuman) | |||||
| self.__logger.info( | |||||
| f"StartSaveHuman: called at {self.__GetTime()}ms") | |||||
| def logStart() -> bool: | |||||
| result = self.__logic.StartSaveHuman() | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"StartSaveHuman: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logStart) | |||||
| def EndSaveHuman(self) -> Future[bool]: | def EndSaveHuman(self) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.EndSaveHuman) | |||||
| self.__logger.info( | |||||
| f"EndSaveHuman: called at {self.__GetTime()}ms") | |||||
| def logEnd() -> bool: | |||||
| result = self.__logic.EndSaveHuman() | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"EndSaveHuman: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logEnd) | |||||
| # Timer用 | # Timer用 | ||||
| def __GetTime(self) -> int: | |||||
| return int((datetime.datetime.now() - self.__startPoint).total_seconds() * 1000) | |||||
| def StartTimer(self) -> None: | def StartTimer(self) -> None: | ||||
| pass | |||||
| self.__startPoint = datetime.datetime.now() | |||||
| self.__logger.info("=== AI.play() ===") | |||||
| self.__logger.info(f"StartTimer: {self.__startPoint.time()}") | |||||
| def EndTimer(self) -> None: | def EndTimer(self) -> None: | ||||
| pass | |||||
| self.__logger.info(f"Time elapsed: {self.__GetTime()}ms") | |||||
| def Play(self, ai: IAI) -> None: | def Play(self, ai: IAI) -> None: | ||||
| pass | |||||
| ai.play(self) | |||||
| class ButcherDebugAPI(IButcherAPI, IGameTimer): | class ButcherDebugAPI(IButcherAPI, IGameTimer): | ||||
| def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None: | def __init__(self, logic: ILogic, file: bool, screen: bool, warnOnly: bool, playerID: int) -> None: | ||||
| self.__logic = logic | self.__logic = logic | ||||
| self.__pool = ProcessPoolExecutor(20) | |||||
| self.__pool = ThreadPoolExecutor(20) | |||||
| self.__logger = logging.getLogger("api " + str(playerID)) | |||||
| self.__logger.setLevel(logging.DEBUG) | |||||
| formatter = logging.Formatter( | |||||
| "[%(name)s] [%(asctime)s] [%(levelname)s] %(message)s", "%H:%M:%S.%e") | |||||
| # 确保文件存在 | |||||
| if not os.path.exists(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs"): | |||||
| os.makedirs(os.path.dirname(os.path.dirname( | |||||
| os.path.realpath(__file__))) + "/logs") | |||||
| fileHandler = logging.FileHandler(os.path.dirname( | |||||
| os.path.dirname(os.path.realpath(__file__))) + "/logs/api-" + str(playerID) + "-log.txt") | |||||
| screenHandler = logging.StreamHandler() | |||||
| if file: | |||||
| fileHandler.setLevel(logging.DEBUG) | |||||
| fileHandler.setFormatter(formatter) | |||||
| self.__logger.addHandler(fileHandler) | |||||
| if screen: | |||||
| if warnOnly: | |||||
| screenHandler.setLevel(logging.WARNING) | |||||
| else: | |||||
| screenHandler.setLevel(logging.INFO) | |||||
| screenHandler.setFormatter(formatter) | |||||
| self.__logger.addHandler(screenHandler) | |||||
| # 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 | # 指挥本角色进行移动,`timeInMilliseconds` 为移动时间,单位为毫秒;`angleInRadian` 表示移动的方向,单位是弧度,使用极坐标——竖直向下方向为 x 轴,水平向右方向为 y 轴 | ||||
| def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]: | def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.Move, timeInMilliseconds, angle) | |||||
| self.__logger.info( | |||||
| f"Move: timeInMilliseconds = {timeInMilliseconds}, angle = {angle}, called at {self.__GetTime()}ms") | |||||
| def logMove() -> bool: | |||||
| result = self.__logic.Move(timeInMilliseconds, angle) | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"Move: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logMove) | |||||
| # 向特定方向移动 | # 向特定方向移动 | ||||
| @@ -157,28 +392,90 @@ class ButcherDebugAPI(IButcherAPI, IGameTimer): | |||||
| # 道具和技能相关 | # 道具和技能相关 | ||||
| def PickProp(self, propType: THUAI6.PropType) -> Future[bool]: | def PickProp(self, propType: THUAI6.PropType) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.PickProp, propType) | |||||
| self.__logger.info( | |||||
| f"PickProp: prop = {propType.name}, called at {self.__GetTime()}ms") | |||||
| def logPick() -> bool: | |||||
| result = self.__logic.PickProp(propType) | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"PickProp: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logPick) | |||||
| def UseProp(self) -> Future[bool]: | def UseProp(self) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.UseProp) | |||||
| self.__logger.info( | |||||
| f"UseProp: called at {self.__GetTime()}ms") | |||||
| def logUse() -> bool: | |||||
| result = self.__logic.UseProp() | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"UseProp: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logUse) | |||||
| def UseSkill(self) -> Future[bool]: | def UseSkill(self) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.UseSkill) | |||||
| self.__logger.info( | |||||
| f"UseSkill: called at {self.__GetTime()}ms") | |||||
| def logUse() -> bool: | |||||
| result = self.__logic.UseSkill() | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"UseSkill: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logUse) | |||||
| # 消息相关,接收消息时无消息则返回(-1, '') | # 消息相关,接收消息时无消息则返回(-1, '') | ||||
| def SendMessage(self, toID: int, message: str) -> Future[bool]: | def SendMessage(self, toID: int, message: str) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.SendMessage, toID, message) | |||||
| self.__logger.info( | |||||
| f"SendMessage: toID = {toID}, message = {message}, called at {self.__GetTime()}ms") | |||||
| def logSend() -> bool: | |||||
| result = self.__logic.SendMessage(toID, message) | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"SendMessage: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logSend) | |||||
| def HaveMessage(self) -> Future[bool]: | def HaveMessage(self) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.HaveMessage) | |||||
| self.__logger.info( | |||||
| f"HaveMessage: called at {self.__GetTime()}ms") | |||||
| def logHave() -> bool: | |||||
| result = self.__logic.HaveMessage() | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"HaveMessage: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logHave) | |||||
| def GetMessage(self) -> Future[tuple[int, str]]: | def GetMessage(self) -> Future[tuple[int, str]]: | ||||
| return self.__pool.submit(self.__logic.GetMessage) | |||||
| self.__logger.info( | |||||
| f"GetMessage: called at {self.__GetTime()}ms") | |||||
| def logGet() -> tuple[int, str]: | |||||
| result = self.__logic.GetMessage() | |||||
| if result[0] == -1: | |||||
| self.__logger.warning( | |||||
| f"GetMessage: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logGet) | |||||
| # 等待下一帧 | # 等待下一帧 | ||||
| def Wait(self) -> Future[bool]: | def Wait(self) -> Future[bool]: | ||||
| self.__logger.info( | |||||
| f"Wait: called at {self.__GetTime()}ms") | |||||
| if self.__logic.GetCounter() == -1: | if self.__logic.GetCounter() == -1: | ||||
| return self.__pool.submit(lambda: False) | return self.__pool.submit(lambda: False) | ||||
| else: | else: | ||||
| @@ -212,39 +509,131 @@ class ButcherDebugAPI(IButcherAPI, IGameTimer): | |||||
| # 用于DEBUG的输出函数,仅在DEBUG模式下有效 | # 用于DEBUG的输出函数,仅在DEBUG模式下有效 | ||||
| def PrintHuman(self) -> None: | |||||
| pass | |||||
| def PrintHuman(self) -> None: | |||||
| for human in self.__logic.GetHumans(): | |||||
| self.__logger.info("******Human Info******") | |||||
| self.__logger.info( | |||||
| f"playerID={human.playerID}, GUID={human.guid}, x={human.x}, y={human.y}") | |||||
| self.__logger.info( | |||||
| f"speed={human.speed}, view range={human.viewRange}, skill time={human.timeUntilSkillAvailable}, prop={human.prop.name}, place={human.place.name}") | |||||
| self.__logger.info( | |||||
| f"state={human.state.name}, life={human.life}, hanged time={human.hangedTime}") | |||||
| self.__logger.info("buff=") | |||||
| humanBuff = "" | |||||
| for buff in human.buff: | |||||
| humanBuff += buff.name + ", " | |||||
| self.__logger.info(humanBuff) | |||||
| self.__logger.info("**********************") | |||||
| def PrintButcher(self) -> None: | def PrintButcher(self) -> None: | ||||
| pass | |||||
| for butcher in self.__logic.GetButchers(): | |||||
| self.__logger.info("******Butcher Info******") | |||||
| self.__logger.info( | |||||
| f"playerID={butcher.playerID}, GUID={butcher.guid}, x={butcher.x}, y={butcher.y}") | |||||
| self.__logger.info( | |||||
| f"speed={butcher.speed}, view range={butcher.viewRange}, skill time={butcher.timeUntilSkillAvailable}, prop={butcher.prop.name}, place={butcher.place.name}") | |||||
| self.__logger.info( | |||||
| f"damage={butcher.damage}, movable={butcher.movable}") | |||||
| self.__logger.info("buff=") | |||||
| butcherBuff = "" | |||||
| for buff in butcher.buff: | |||||
| butcherBuff += buff.name + ", " | |||||
| self.__logger.info(butcherBuff) | |||||
| self.__logger.info("************************") | |||||
| def PrintProp(self) -> None: | def PrintProp(self) -> None: | ||||
| pass | |||||
| for prop in self.__logic.GetProps(): | |||||
| self.__logger.info("******Prop Info******") | |||||
| self.__logger.info( | |||||
| f"GUID={prop.guid}, x={prop.x}, y={prop.y}, place={prop.place.name}, is moving={prop.isMoving}") | |||||
| self.__logger.info("*********************") | |||||
| def PrintSelfInfo(self) -> None: | def PrintSelfInfo(self) -> None: | ||||
| pass | |||||
| mySelf = self.__logic.GetSelfInfo() | |||||
| self.__logger.info("******Self Info******") | |||||
| self.__logger.info( | |||||
| f"playerID={mySelf.playerID}, GUID={mySelf.guid}, x={mySelf.x}, y={mySelf.y}") | |||||
| self.__logger.info( | |||||
| f"speed={mySelf.speed}, view range={mySelf.viewRange}, skill time={mySelf.timeUntilSkillAvailable}, prop={mySelf.prop.name}, place={mySelf.place.name}") | |||||
| if isinstance(mySelf, THUAI6.Human): | |||||
| self.__logger.info( | |||||
| f"state={mySelf.state.name}, life={mySelf.life}, hanged time={mySelf.hangedTime}") | |||||
| else: | |||||
| self.__logger.info( | |||||
| f"damage={mySelf.damage}, movable={mySelf.movable}") | |||||
| self.__logger.info("buff=") | |||||
| mySelfBuff = "" | |||||
| for buff in mySelf.buff: | |||||
| mySelfBuff += buff.name + ", " | |||||
| self.__logger.info(mySelfBuff) | |||||
| self.__logger.info("*********************") | |||||
| # 屠夫阵营的特殊函数 | # 屠夫阵营的特殊函数 | ||||
| def Attack(self, angle: float) -> Future[bool]: | def Attack(self, angle: float) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.Attack, angle) | |||||
| self.__logger.info( | |||||
| f"Attack: angle = {angle}, called at {self.__GetTime()}ms") | |||||
| def logAttack() -> bool: | |||||
| result = self.__logic.Attack(angle) | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"Attack: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logAttack) | |||||
| def CarryHuman(self) -> Future[bool]: | def CarryHuman(self) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.CarryHuman) | |||||
| self.__logger.info( | |||||
| f"CarryHuman: called at {self.__GetTime()}ms") | |||||
| def logCarry() -> bool: | |||||
| result = self.__logic.CarryHuman() | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"CarryHuman: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logCarry) | |||||
| def ReleaseHuman(self) -> Future[bool]: | def ReleaseHuman(self) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.ReleaseHuman) | |||||
| self.__logger.info( | |||||
| f"ReleaseHuman: called at {self.__GetTime()}ms") | |||||
| def logRelease() -> bool: | |||||
| result = self.__logic.ReleaseHuman() | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"ReleaseHuman: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logRelease) | |||||
| def HangHuman(self) -> Future[bool]: | def HangHuman(self) -> Future[bool]: | ||||
| return self.__pool.submit(self.__logic.HangHuman) | |||||
| self.__logger.info( | |||||
| f"HangHuman: called at {self.__GetTime()}ms") | |||||
| def logHang() -> bool: | |||||
| result = self.__logic.HangHuman() | |||||
| if not result: | |||||
| self.__logger.warning( | |||||
| f"HangHuman: failed at {self.__GetTime()}ms") | |||||
| return result | |||||
| return self.__pool.submit(logHang) | |||||
| # Timer用 | # Timer用 | ||||
| def __GetTime(self) -> int: | |||||
| return int((datetime.datetime.now() - self.__startPoint).total_seconds() * 1000) | |||||
| def StartTimer(self) -> None: | def StartTimer(self) -> None: | ||||
| pass | |||||
| self.__startPoint = datetime.datetime.now() | |||||
| self.__logger.info("=== AI.play() ===") | |||||
| self.__logger.info(f"StartTimer: {self.__startPoint.time()}") | |||||
| def EndTimer(self) -> None: | def EndTimer(self) -> None: | ||||
| pass | |||||
| self.__logger.info(f"Time elapsed: {self.__GetTime()}ms") | |||||
| def Play(self, ai: IAI) -> None: | def Play(self, ai: IAI) -> None: | ||||
| pass | |||||
| ai.play(self) | |||||
| @@ -68,47 +68,60 @@ class Logic(ILogic): | |||||
| def GetButchers(self) -> List[THUAI6.Butcher]: | def GetButchers(self) -> List[THUAI6.Butcher]: | ||||
| with self.__mtxState: | with self.__mtxState: | ||||
| self.__logger.debug("Called GetButchers") | |||||
| return self.__currentState.butchers | return self.__currentState.butchers | ||||
| def GetHumans(self) -> List[THUAI6.Human]: | def GetHumans(self) -> List[THUAI6.Human]: | ||||
| with self.__mtxState: | with self.__mtxState: | ||||
| self.__logger.debug("Called GetHumans") | |||||
| return self.__currentState.humans | return self.__currentState.humans | ||||
| def GetProps(self) -> List[THUAI6.Prop]: | def GetProps(self) -> List[THUAI6.Prop]: | ||||
| with self.__mtxState: | with self.__mtxState: | ||||
| self.__logger.debug("Called GetProps") | |||||
| return self.__currentState.props | return self.__currentState.props | ||||
| def GetSelfInfo(self) -> Union[THUAI6.Human, THUAI6.Butcher]: | def GetSelfInfo(self) -> Union[THUAI6.Human, THUAI6.Butcher]: | ||||
| with self.__mtxState: | with self.__mtxState: | ||||
| self.__logger.debug("Called GetSelfInfo") | |||||
| return self.__currentState.self | return self.__currentState.self | ||||
| def GetFullMap(self) -> List[List[THUAI6.PlaceType]]: | def GetFullMap(self) -> List[List[THUAI6.PlaceType]]: | ||||
| with self.__mtxState: | with self.__mtxState: | ||||
| self.__logger.debug("Called GetFullMap") | |||||
| return self.__currentState.map | return self.__currentState.map | ||||
| def GetPlaceType(self, x: int, y: int) -> THUAI6.PlaceType: | def GetPlaceType(self, x: int, y: int) -> THUAI6.PlaceType: | ||||
| with self.__mtxState: | with self.__mtxState: | ||||
| self.__logger.debug("Called GetPlaceType") | |||||
| return self.__currentState.map[x][y] | return self.__currentState.map[x][y] | ||||
| def Move(self, time: int, angle: float) -> bool: | def Move(self, time: int, angle: float) -> bool: | ||||
| self.__logger.debug("Called Move") | |||||
| return self.__comm.Move(time, angle, self.__playerID) | return self.__comm.Move(time, angle, self.__playerID) | ||||
| def PickProp(self, propType: THUAI6.PropType) -> bool: | def PickProp(self, propType: THUAI6.PropType) -> bool: | ||||
| self.__logger.debug("Called PickProp") | |||||
| return self.__comm.PickProp(propType, self.__playerID) | return self.__comm.PickProp(propType, self.__playerID) | ||||
| def UseProp(self) -> bool: | def UseProp(self) -> bool: | ||||
| self.__logger.debug("Called UseProp") | |||||
| return self.__comm.UseProp(self.__playerID) | return self.__comm.UseProp(self.__playerID) | ||||
| def UseSkill(self) -> bool: | def UseSkill(self) -> bool: | ||||
| self.__logger.debug("Called UseSkill") | |||||
| return self.__comm.UseSkill(self.__playerID) | return self.__comm.UseSkill(self.__playerID) | ||||
| def SendMessage(self, toID: int, message: str) -> bool: | def SendMessage(self, toID: int, message: str) -> bool: | ||||
| self.__logger.debug("Called SendMessage") | |||||
| return self.__comm.SendMessage(toID, message, self.__playerID) | return self.__comm.SendMessage(toID, message, self.__playerID) | ||||
| def HaveMessage(self) -> bool: | def HaveMessage(self) -> bool: | ||||
| self.__logger.debug("Called HaveMessage") | |||||
| return self.__comm.HaveMessage() | return self.__comm.HaveMessage() | ||||
| def GetMessage(self) -> tuple[int, str]: | def GetMessage(self) -> tuple[int, str]: | ||||
| self.__logger.debug("Called GetMessage") | |||||
| return self.__comm.GetMessage() | return self.__comm.GetMessage() | ||||
| def WaitThread(self) -> bool: | def WaitThread(self) -> bool: | ||||
| @@ -126,51 +139,65 @@ class Logic(ILogic): | |||||
| # IHumanAPI使用的接口 | # IHumanAPI使用的接口 | ||||
| def Escape(self) -> bool: | def Escape(self) -> bool: | ||||
| self.__logger.debug("Called Escape") | |||||
| return self.__comm.Escape(self.__playerID) | return self.__comm.Escape(self.__playerID) | ||||
| def StartFixMachine(self) -> bool: | def StartFixMachine(self) -> bool: | ||||
| self.__logger.debug("Called StartFixMachine") | |||||
| return self.__comm.StartFixMachine(self.__playerID) | return self.__comm.StartFixMachine(self.__playerID) | ||||
| def EndFixMachine(self) -> bool: | def EndFixMachine(self) -> bool: | ||||
| self.__logger.debug("Called EndFixMachine") | |||||
| return self.__comm.EndFixMachine(self.__playerID) | return self.__comm.EndFixMachine(self.__playerID) | ||||
| def StartSaveHuman(self) -> bool: | def StartSaveHuman(self) -> bool: | ||||
| self.__logger.debug("Called StartSaveHuman") | |||||
| return self.__comm.StartSaveHuman(self.__playerID) | return self.__comm.StartSaveHuman(self.__playerID) | ||||
| def EndSaveHuman(self) -> bool: | def EndSaveHuman(self) -> bool: | ||||
| self.__logger.debug("Called EndSaveHuman") | |||||
| return self.__comm.EndSaveHuman(self.__playerID) | return self.__comm.EndSaveHuman(self.__playerID) | ||||
| # Butcher使用的接口 | # Butcher使用的接口 | ||||
| def Attack(self, angle: float) -> bool: | def Attack(self, angle: float) -> bool: | ||||
| self.__logger.debug("Called Attack") | |||||
| return self.__comm.Attack(angle, self.__playerID) | return self.__comm.Attack(angle, self.__playerID) | ||||
| def CarryHuman(self) -> bool: | def CarryHuman(self) -> bool: | ||||
| self.__logger.debug("Called CarryHuman") | |||||
| return self.__comm.CarryHuman(self.__playerID) | return self.__comm.CarryHuman(self.__playerID) | ||||
| def ReleaseHuman(self) -> bool: | def ReleaseHuman(self) -> bool: | ||||
| self.__logger.debug("Called ReleaseHuman") | |||||
| return self.__comm.ReleaseHuman(self.__playerID) | return self.__comm.ReleaseHuman(self.__playerID) | ||||
| def HangHuman(self) -> bool: | def HangHuman(self) -> bool: | ||||
| self.__logger.debug("Called HangHuman") | |||||
| return self.__comm.HangHuman(self.__playerID) | return self.__comm.HangHuman(self.__playerID) | ||||
| # Logic内部逻辑 | # Logic内部逻辑 | ||||
| def __TryConnection(self) -> bool: | def __TryConnection(self) -> bool: | ||||
| self.__logger.info("Try to connect to server...") | |||||
| return self.__comm.TryConnection(self.__playerID) | return self.__comm.TryConnection(self.__playerID) | ||||
| def __ProcessMessage(self) -> None: | def __ProcessMessage(self) -> None: | ||||
| def messageThread(): | def messageThread(): | ||||
| self.__logger.info("Message thread start!") | |||||
| self.__comm.AddPlayer(self.__playerID) | self.__comm.AddPlayer(self.__playerID) | ||||
| self.__logger.info("Join the player!") | |||||
| self.__comm.ReadMessage(self.__playerID) | self.__comm.ReadMessage(self.__playerID) | ||||
| while self.__gameState != THUAI6.GameState.GameEnd: | while self.__gameState != THUAI6.GameState.GameEnd: | ||||
| # 读取消息,无消息时此处阻塞 | # 读取消息,无消息时此处阻塞 | ||||
| clientMsg = self.__comm.GetMessage2Client() | clientMsg = self.__comm.GetMessage2Client() | ||||
| self.__logger.debug("Get message from server!") | |||||
| self.__gameState = Proto2THUAI6.gameStateDict[ | self.__gameState = Proto2THUAI6.gameStateDict[ | ||||
| clientMsg.game_state] | clientMsg.game_state] | ||||
| if self.__gameState == THUAI6.GameState.GameStart: | if self.__gameState == THUAI6.GameState.GameStart: | ||||
| # 读取玩家的GUID | # 读取玩家的GUID | ||||
| self.__logger.info("Game start!") | |||||
| self.__playerGUIDs.clear() | self.__playerGUIDs.clear() | ||||
| for human in clientMsg.human_message: | for human in clientMsg.human_message: | ||||
| self.__playerGUIDs.append(human.guid) | self.__playerGUIDs.append(human.guid) | ||||
| @@ -194,12 +221,15 @@ class Logic(ILogic): | |||||
| self.__bufferState.guids = self.__playerGUIDs | self.__bufferState.guids = self.__playerGUIDs | ||||
| self.__LoadBuffer(clientMsg) | self.__LoadBuffer(clientMsg) | ||||
| else: | else: | ||||
| self.__logger.error("Unknown GameState!") | |||||
| continue | continue | ||||
| self.__AILoop = False | self.__AILoop = False | ||||
| with self.__cvBuffer: | with self.__cvBuffer: | ||||
| self.__bufferUpdated = True | self.__bufferUpdated = True | ||||
| self.__counterBuffer = -1 | self.__counterBuffer = -1 | ||||
| self.__cvBuffer.notify() | self.__cvBuffer.notify() | ||||
| self.__logger.info("Game End!") | |||||
| self.__logger.info("Message thread end!") | |||||
| threading.Thread(target=messageThread).start() | threading.Thread(target=messageThread).start() | ||||
| @@ -208,6 +238,7 @@ class Logic(ILogic): | |||||
| self.__bufferState.humans.clear() | self.__bufferState.humans.clear() | ||||
| self.__bufferState.butchers.clear() | self.__bufferState.butchers.clear() | ||||
| self.__bufferState.props.clear() | self.__bufferState.props.clear() | ||||
| self.__logger.debug("Buffer cleared!") | |||||
| self.__bufferState.map = Proto2THUAI6.Protobuf2THUAI6Map( | self.__bufferState.map = Proto2THUAI6.Protobuf2THUAI6Map( | ||||
| message.map_message) | message.map_message) | ||||
| if Setting.playerType() == THUAI6.PlayerType.HumanPlayer: | if Setting.playerType() == THUAI6.PlayerType.HumanPlayer: | ||||
| @@ -217,6 +248,7 @@ class Logic(ILogic): | |||||
| human) | human) | ||||
| self.__bufferState.humans.append( | self.__bufferState.humans.append( | ||||
| Proto2THUAI6.Protobuf2THUAI6Human(human)) | Proto2THUAI6.Protobuf2THUAI6Human(human)) | ||||
| self.__logger.debug("Add Human!") | |||||
| for butcher in message.butcher_message: | for butcher in message.butcher_message: | ||||
| viewRange: int = self.__bufferState.self.viewRange | viewRange: int = self.__bufferState.self.viewRange | ||||
| deltaX: int = butcher.x - self.__bufferState.self.x | deltaX: int = butcher.x - self.__bufferState.self.x | ||||
| @@ -235,6 +267,7 @@ class Logic(ILogic): | |||||
| else: | else: | ||||
| self.__bufferState.butchers.append( | self.__bufferState.butchers.append( | ||||
| Proto2THUAI6.Protobuf2THUAI6Butcher(butcher)) | Proto2THUAI6.Protobuf2THUAI6Butcher(butcher)) | ||||
| self.__logger.debug("Add Butcher!") | |||||
| else: | else: | ||||
| for butcher in message.butcher_message: | for butcher in message.butcher_message: | ||||
| if butcher.player_id == self.__playerID: | if butcher.player_id == self.__playerID: | ||||
| @@ -242,6 +275,7 @@ class Logic(ILogic): | |||||
| butcher) | butcher) | ||||
| self.__bufferState.butchers.append( | self.__bufferState.butchers.append( | ||||
| Proto2THUAI6.Protobuf2THUAI6Butcher(butcher)) | Proto2THUAI6.Protobuf2THUAI6Butcher(butcher)) | ||||
| self.__logger.debug("Add Butcher!") | |||||
| for human in message.human_message: | for human in message.human_message: | ||||
| viewRange: int = self.__bufferState.self.viewRange | viewRange: int = self.__bufferState.self.viewRange | ||||
| deltaX: int = human.x - self.__bufferState.self.x | deltaX: int = human.x - self.__bufferState.self.x | ||||
| @@ -260,23 +294,21 @@ class Logic(ILogic): | |||||
| else: | else: | ||||
| self.__bufferState.humans.append( | self.__bufferState.humans.append( | ||||
| Proto2THUAI6.Protobuf2THUAI6Human(human)) | Proto2THUAI6.Protobuf2THUAI6Human(human)) | ||||
| self.__logger.debug("Add Human!") | |||||
| for prop in message.prop_message: | for prop in message.prop_message: | ||||
| self.__bufferState.props.append( | self.__bufferState.props.append( | ||||
| Proto2THUAI6.Protobuf2THUAI6Prop(prop)) | Proto2THUAI6.Protobuf2THUAI6Prop(prop)) | ||||
| self.__logger.debug("Add Prop!") | |||||
| if Setting.asynchronous(): | if Setting.asynchronous(): | ||||
| with self.__mtxState: | with self.__mtxState: | ||||
| self.__currentState, self.__bufferState = self.__bufferState, self.__currentState | self.__currentState, self.__bufferState = self.__bufferState, self.__currentState | ||||
| self.__logger.info("Update state!") | |||||
| self.__freshed = True | self.__freshed = True | ||||
| else: | else: | ||||
| self.__bufferUpdated = True | self.__bufferUpdated = True | ||||
| self.__counterBuffer += 1 | self.__counterBuffer += 1 | ||||
| self.__cvBuffer.notify() | self.__cvBuffer.notify() | ||||
| def __UnBlockBuffer(self) -> None: | |||||
| with self.__cvBuffer: | |||||
| self.__bufferUpdated = True | |||||
| self.__cvBuffer.notify() | |||||
| def __UnBlockAI(self) -> None: | def __UnBlockAI(self) -> None: | ||||
| with self.__cvAI: | with self.__cvAI: | ||||
| self.__AIStart = True | self.__AIStart = True | ||||
| @@ -289,6 +321,7 @@ class Logic(ILogic): | |||||
| self.__bufferState, self.__currentState = self.__currentState, self.__bufferState | self.__bufferState, self.__currentState = self.__currentState, self.__bufferState | ||||
| self.__bufferUpdated = False | self.__bufferUpdated = False | ||||
| self.__counterState = self.__counterBuffer | self.__counterState = self.__counterBuffer | ||||
| self.__logger.info("Update state!") | |||||
| def __Wait(self) -> None: | def __Wait(self) -> None: | ||||
| self.__freshed = False | self.__freshed = False | ||||
| @@ -300,7 +333,7 @@ class Logic(ILogic): | |||||
| # 建立日志组件 | # 建立日志组件 | ||||
| self.__logger.setLevel(logging.DEBUG) | self.__logger.setLevel(logging.DEBUG) | ||||
| formatter = logging.Formatter( | formatter = logging.Formatter( | ||||
| "[%(asctime)s][%(name)s][%(levelname)s] %(message)s", "%H:%M:%S.%e") | |||||
| "[%(name)s] [%(asctime)s] [%(levelname)s] %(message)s", "%H:%M:%S.%e") | |||||
| # 确保文件存在 | # 确保文件存在 | ||||
| if not os.path.exists(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs"): | if not os.path.exists(os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + "/logs"): | ||||
| os.makedirs(os.path.dirname(os.path.dirname( | os.makedirs(os.path.dirname(os.path.dirname( | ||||
| @@ -325,8 +358,7 @@ class Logic(ILogic): | |||||
| self.__logger.info("asynchronous: %s", Setting.asynchronous()) | self.__logger.info("asynchronous: %s", Setting.asynchronous()) | ||||
| self.__logger.info("server: %s:%s", IP, port) | self.__logger.info("server: %s:%s", IP, port) | ||||
| self.__logger.info("playerID: %s", self.__playerID) | self.__logger.info("playerID: %s", self.__playerID) | ||||
| self.__logger.info("player type: %s", | |||||
| THUAI6.playerTypeDict[Setting.playerType()]) | |||||
| self.__logger.info("player type: %s", Setting.playerType().name) | |||||
| self.__logger.info("****************************") | self.__logger.info("****************************") | ||||
| # 建立通信组件 | # 建立通信组件 | ||||
| @@ -365,10 +397,14 @@ class Logic(ILogic): | |||||
| self.__timer.EndTimer() | self.__timer.EndTimer() | ||||
| if self.__TryConnection(): | if self.__TryConnection(): | ||||
| self.__logger.info( | |||||
| "Connect to the server successfully, AI thread will be started.") | |||||
| self.__threadAI = threading.Thread(target=AIThread) | self.__threadAI = threading.Thread(target=AIThread) | ||||
| self.__threadAI.start() | self.__threadAI.start() | ||||
| self.__ProcessMessage() | self.__ProcessMessage() | ||||
| self.__logger.info("Join the AI thread.") | |||||
| self.__threadAI.join() | self.__threadAI.join() | ||||
| else: | else: | ||||
| self.__AILoop = False | self.__AILoop = False | ||||
| self.__logger.error("Failed to connect to the server.") | |||||
| return | return | ||||
| @@ -103,57 +103,3 @@ class Prop: | |||||
| place: PlaceType | place: PlaceType | ||||
| facingDirection: float | facingDirection: float | ||||
| isMoving: bool | isMoving: bool | ||||
| gameStateDict: Dict[GameState, str] = { | |||||
| GameState.NullGameState: "NullGameState", | |||||
| GameState.GameStart: "GameStart", | |||||
| GameState.GameRunning: "GameRunning", | |||||
| GameState.GameEnd: "GameEnd"} | |||||
| humanStateDict: Dict[HumanState, str] = { | |||||
| HumanState.NullHumanState: "NullHumanState", | |||||
| HumanState.Idle: "Idle", | |||||
| HumanState.Fixing: "Fixing", | |||||
| HumanState.Dying: "Dying", | |||||
| HumanState.OnChair: "OnChair", | |||||
| HumanState.Dead: "Dead"} | |||||
| playerTypeDict: Dict[PlayerType, str] = { | |||||
| PlayerType.NullPlayerType: "NullPlayerType", | |||||
| PlayerType.HumanPlayer: "HumanPlayer", | |||||
| PlayerType.ButcherPlayer: "ButcherPlayer"} | |||||
| propTypeDict: Dict[PropType, str] = { | |||||
| PropType.NullPropType: "NullPropType", | |||||
| PropType.PropType1: "PropType1"} | |||||
| humanTypeDict: Dict[HumanType, str] = { | |||||
| HumanType.NullHumanType: "NullHumanType", | |||||
| HumanType.HumanType1: "HumanType1"} | |||||
| butcherTypeDict: Dict[ButcherType, str] = { | |||||
| ButcherType.NullButcherType: "NullButcherType", | |||||
| ButcherType.ButcherType1: "ButcherType1"} | |||||
| humanBuffTypeDict: Dict[HumanBuffType, str] = { | |||||
| HumanBuffType.NullHumanBuffType: "NullHumanBuffType", | |||||
| HumanBuffType.HumanBuffType1: "HumanBuffType1"} | |||||
| butcherBuffTypeDict: Dict[ButcherBuffType, str] = { | |||||
| ButcherBuffType.NullButcherBuffType: "NullButcherBuffType", | |||||
| ButcherBuffType.ButcherBuffType1: "ButcherBuffType1"} | |||||
| placeTypeDict: Dict[PlaceType, str] = { | |||||
| PlaceType.NullPlaceType: "NullPlaceType", | |||||
| PlaceType.Land: "Land", | |||||
| PlaceType.Wall: "Wall", | |||||
| PlaceType.Grass: "Grass", | |||||
| PlaceType.Machine: "Machine", | |||||
| PlaceType.Gate: "Gate", | |||||
| PlaceType.HiddenGate: "HiddenGate"} | |||||
| shapeTypeDict: Dict[ShapeType, str] = { | |||||
| ShapeType.NullShapeType: "NullShapeType", | |||||
| ShapeType.Square: "Square", | |||||
| ShapeType.Circle: "Circle"} | |||||