Пример #1
0
 def newTemplate(
         self,
         name,
         imgPath,
         default_threshold=0.98,  # 默认识别度
         onload=False,  # 是否直接加载
         showlog=False):  # 是否显示成功添加
     if name[0] not in string.ascii_letters:
         logger.error(f'名字首位必须为字母字符:{name}')
         return None
     if not os.path.isfile(imgPath):
         logger.error("图片不存在:" + imgPath)
         return None
     if name not in self.__namelist__:
         temp = None
         if onload:
             temp = cv2.imread(imgPath)
         if isinstance(temp, type(None)) and onload:
             logger.error("未找到%s的图片[位于\'%s\']" % (name, imgPath))
             return None
         setattr(self, name, [temp, imgPath, default_threshold, onload])
         self.addName(name)
         if showlog:
             logger.debug("成功添加定位标志%s" % name)
     else:
         try:
             setattr(
                 self, name,
                 [cv2.imread(imgPath), imgPath, default_threshold, True])
             logger.warning("已覆盖名为%s的定位标志" % name)
         except:
             logger.warning('在覆盖标志时出现错误')
         return None
Пример #2
0
 def _writeStageDrop_Ver2(self, stageId, dropList, cost_time: float = 0, raw_finish_time: int = 0):
     """
     :param stageId: type str for read file {stageId}.drp
     :param dropList: recognizeEndItemsWithTag() return's
     :param cost_time: cost time of attack
     :param raw_finish_time:原始完成时间
     :return: None
     :writeStructure: ([version \x02][len(droplist)<1>][[itemid<2>][quantity<2>][type<1>]]..[atk_time<3>][time<4>])
     """
     sv = []
     for i in dropList:
         _q = i['quantity']
         if _q > 0:
             sv.append([self.get(i['name']), _q, i['type']])
     if len(sv) == 0:
         logger.warning(f"EMPTY DropList as Stage<{stageId}>")
         return
     with open(f"{DROPFOLDER_PATH}{stageId}.drp", 'ab') as fd:
         fd.write(b'\x02')
         fd.write(len(sv).to_bytes(1, 'little'))
         for i, q, t in sv:
             fd.write(i.to_bytes(2, 'little'))
             fd.write(q.to_bytes(2, 'little'))
             fd.write((t + 1).to_bytes(1, 'little'))
         try:
             fd.write(int(cost_time * 100).to_bytes(3, 'little'))
         except OverflowError:
             logger.warning(f"cannot convert cost_time({cost_time}) into byte!")
             fd.write(b'\xff\xff\xff')
         fd.write(int(raw_finish_time or time.time()).to_bytes(4, 'little'))
Пример #3
0
def recognizeOperation(image, map_dict=None) -> Tuple[str, str]:
    if not map_dict:
        map_dict = getMapCost()
    opidtext = fix_known_data(load_data()[1].recognize2(
        image, subset='0123456789abcdefghijklmnopqrstuvwxyz-')[0])

    where_ = map_dict.where(opidtext)
    if where_:
        return opidtext, where_
    # 无法识别,尝试使用tesseract
    logger.warning("无法识别地图信息" + opidtext)
    debug_ret = []
    import pytesseract
    for index in range(10):
        ret = pytesseract.image_to_string(image, lang="eng") \
            .replace("\n", "").replace("\x0c", "")
        where_ = map_dict.where(ret)
        debug_ret.append(ret)
        if where_:
            logger.debug("识别信息:%s" % str(debug_ret))
            return ret, where_

    logger.error("在10次识别后依旧无法识别出当前关卡信息。")
    logger.debug("识别信息:%s" % str(debug_ret))
    return "", ""
Пример #4
0
 def createMap(self, name):
     if self.config.get(name) is None:
         self.config.update({name: []})
         return True
     else:
         logger.warning("已存在名为%s的数据" % name)
         return False
Пример #5
0
 def readFile(self, filename):
     if not os.path.exists(filename):
         logger.warning("%s不存在,自动创建!" % filename)
         fn = '.\\' + filename
         f = open(fn, 'w')
         f.write('')
         f.close()
     self._filename = filename
     self.data = open(filename, 'rb')
     self._fileopen = True
Пример #6
0
def recognizeEndItems(ark, stageCode, quantity=True):
    drop_list = getDropList(stageCode)
    for i in getActivityOpen()[1]:
        drop_list.add((i, getItemTag()['items'][i].get('name', "未知物品:" + i)))
    # drop_list = list(drop_list)
    # return drop_list
    screen = ark.getScreenShot(470, 520, 800, 160)
    drop_reco = []
    for item, name in drop_list:
        try:
            rep, where = ark.gameTemp.matchDifference(
                screen,
                cv2.resize(
                    ark.gameTemp.getTemplate("lootitem\\" + item + ".png")[0],
                    itemReco.STAGE_DROP)[29:29 + 46, 34:34 + 68],
                method=1)
        except cv2.error as cverr:
            logger.warning(
                f"处理掉落物'{name}'失败:(code={cverr.code}){cverr.err} in function '{cverr.func}'"
            )
            continue
        y, x, num = -1, -1, -1
        if rep >= 0.9:
            y, x = int(where[0]), int(where[1])
            x += 26
            y += 63
            if quantity:
                imgraw = Image.fromarray(screen[y:y + 27, x:x + 53])
                numimg = imgops.crop_blackedge2(imgraw, 120)
                if numimg is None or numimg.size < (5, 5):
                    numimg = imgops.clear_background(imgraw, threshold=180)
                # cv2.imshow("d",np.asarray(numimg)); cv2.waitKey(0)
                img = imgops.clear_background(numimg, threshold=120)
                # cv2.imshow("i", np.asarray(img)); cv2.waitKey(0)
                reco = ark.reconizerN.recognize2(img, subset="0123456789万")
                try:
                    num = int(reco[0]) if reco != '' else 0
                except:
                    num = 0
            else:
                num = -1
        err = rep > 0.9 and num <= 0
        if err:
            logger.warning(f"识别到物品\"{name}\"数量出现异常,已置零,该物品将不计入统计中")
        # drop_reco.append([name, rep > 0.9, rep, [x, y], num])
        drop_reco.append({
            "name": name,
            "have": rep > 0.9,
            "_acq": rep,
            "_pos": (x, y),
            "quantity": num,
            "error": err
        })
    return drop_reco
Пример #7
0
 def update_droprate_processing(self, stage, item, droprate, mode='add'):
     if stage not in self.stage_name_rv['zh']:
         logger.warning(f'stage {stage} not found')
         return
     if item not in self.item_name_rv:
         logger.warning(f'item {item} not found')
         return
     stageid = self.stage_name_rv['zh'][stage]
     itemid = self.item_name_rv[item]
     if mode == 'add':
         self.probs_matrix[stageid][itemid] += droprate
     elif mode == 'update':
         self.probs_matrix[stageid][itemid] = droprate
Пример #8
0
 def addStage(self, stageName, times, require=None, append=False):
     if stageName in self['list']:
         if append is self:
             logger.warning(
                 f"已存在名为{stageName}的关卡在攻击列表中,若需要添加请使用append=True更新攻击次数")
             return self
         else:
             self['stages'][self['list'].index(
                 stageName)]["max_atk"] += times
             return self
     self["list"].append(stageName)
     self['stages'].append(Stage(stageName, times, require))
     return self
Пример #9
0
 def toMain(self):
     if self.__ark.getLocation(self.__ark.getScreenShot(), 'main'):
         return True
     if self.__ark.gameTemp.dingwei(
             "main\\main_ref.png",
             self.__ark.getScreenShot(199, 11, 141, 53)):
         logger.warning('未知识别位置!强制返回主界面并从主界面进行操作,可能会导致异常产生!')
         self.__ark.clicker.mouse_click(269, 39, t=0.7)
         self.__ark.clicker.mouse_click(93, 172, t=2)
         # TODO:检查事件
         self.__ark.check_to_main_notice()
         return True
     return False
Пример #10
0
 def fromPlanner(planned_data, require_request=False):
     if not isinstance(planned_data, dict):
         logger.error(
             f"规划数据并非dict形式,请检查(获得了{planned_data.__class__.__name__})")
         return StageSet()
     stages = planned_data.get("stages", [])
     if not stages:
         logger.warning("规划数据关卡列表为空!")
         return StageSet()
     ret = StageSet()
     for stage in stages:
         ret.addStage(stage['stage'], int(float(stage['count']) + 0.9),
                      stage['items'], require_request)
     return ret
Пример #11
0
 def wrapper(*args, **kwargs):
     if isinstance(arg, str):
         if update or not RootData.has(arg):
             ret = func(*args, **kwargs)
             cache_time = 0 if max_cache_time < 0 else time.time(
             ) + max_cache_time
             RootData.set(arg, ret, cache_time)
             return ret
         else:
             return RootData.get(arg)
     else:
         logger.warning("cache can't store name for type of %s" %
                        arg.__class__.__name__)
         return func(*args, **kwargs)
Пример #12
0
 def addMap(self, name, condition=None):
     if '.' in name:
         name_bef, name_after = name.split('.', 1)
         if not self.mapping.get('map').has(name_bef):
             logger.warning(name + " doesn't in the MapList")
             return False
         self.mapping.get('map').get(name_bef).get('addon').addAddon(name_after)
     else:
         if self.mapping.get("map").has(name):
             logger.warning(name + " has already in the MapList")
             return False
         self.mapping.get("map").update(self._default_map_template(name, condition=condition))
         self.mapping.get("reflector").push(name, name, create=True)
     return True
Пример #13
0
 def addItemFromRawDict(self, dumpdict: dict):
     if dumpdict.get('type') in ['FURN', 'CHAR', 'NONE', 'ET_STAGE']:
         logger.warning(
             f"cannot add type:{dumpdict.get('type')} into ItemStack")
         return self
     try:
         return self.addItem(
             getItemTag()['items'].get(dumpdict.get('id'))['name'],
             int(dumpdict.get('count')))
     except:
         logger.warning(
             f"cannot add [T:{dumpdict.get('type')} I:{dumpdict.get('id')}] into ItemStack"
         )
     return self
Пример #14
0
 def moveStageInMap(self, mapName, stage1, stage2, error=True):
     # 承接changestageinmap,在识别到两个stage基础上进行stage内移动
     rect = self.getMapStageInfo(mapName)
     rect_stage = [os.path.basename(i)[:-4] for i, v in rect]
     assert rect != []
     if error:
         stage1 = rect_stage[0]
     else:
         assert stage1 in rect_stage
     x, y = rect[rect_stage.index(stage1)][1]
     # print(rect, stage1, stage2, rect_stage)
     dx, dy = self.getDistanceBetweenStage(mapName, stage1, stage2)
     if 0 < dx + x < 1240 and 50 < dy + y < 618:
         # print(x, dx, y, dy)
         self.__ark.clicker.mouse_click(x + dx + 35, y + dy + 13, t=1)
         return True
     while abs(dx) > 669:
         self.__ark.clicker.dragRel(1172, 35, ((-1 if dx > 0 else 1) * 400),
                                    0)
         self.__ark.clicker.mouse_click(510, 35, t=0.2)
         dx += (-1 if dx > 0 else 1) * 660
     while abs(dx) > 172:
         self.__ark.clicker.dragRel(1172, 35, ((-1 if dx > 0 else 1) * 100),
                                    0)
         self.__ark.clicker.mouse_click(510, 35, t=0.2)
         dx += (-1 if dx > 0 else 1) * 172
     while abs(dx) > 70:
         self.__ark.clicker.dragRel(1172, 35, ((-1 if dx > 0 else 1) * 50),
                                    0)
         self.__ark.clicker.mouse_click(510, 35, t=0.2)
         dx += (-1 if dx > 0 else 1) * 70
     # print(x + dx, y + dy)
     reco = self.getMapStageInfo(mapName)
     reco_li = [os.path.basename(i)[:-4] for i, v in reco]
     if stage2 in reco_li:
         cur_x, cur_y = reco[reco_li.index(stage2)][1]
         self.__ark.clicker.mouse_click(cur_x + 35, cur_y + 13, t=1)
         return True
     else:
         logger.warning(f"{stage2} not found in current map")
         self.moveStageInMap(mapName, stage1, stage2)
Пример #15
0
 def _writeStageDrop_Ver1(self, stageId: str, dropList: dict, cost_time: float = 0):
     """
     :param stageId: type str for read file {stageId}.drp
     :param dropList: recognizeEndItemsWithTag() return's
     :return: None
     :writeStructure: ([version \x01][len(droplist)<1>][[itemid<2>][quantity<2>]]..[time<4>])
     """
     sv = []
     for i in dropList:
         if i['have']:
             _q = i['quantity']
             if _q > 0:
                 sv.append([self.get(i['name']), _q])
     if len(sv) == 0:
         logger.warning(f"EMPTY DropList as Stage<{stageId}>")
         return
     with open(f"{DROPFOLDER_PATH}{stageId}.drp", 'ab') as fd:
         fd.write(b'\x01')
         fd.write(len(sv).to_bytes(1, 'little'))
         for i, q in sv:
             fd.write(i.to_bytes(2, 'little'))
             fd.write(q.to_bytes(2, 'little'))
         fd.write(int(time.time()).to_bytes(4, 'little'))
Пример #16
0
def UpgradeDropFromVer1_ToVer2(ark, stage, force=False):
    drp = getStageTag().getStage(stage).getDropInfo().getDropList()
    li = list(i[1] for i in drp)
    se = set(i[1] for i in drp)
    if len(li) != len(se):
        logger.warning('Unable to upgrade the level with different drop overlaps from Ver.1 to Ver.2!')
        if not force:
            return False
    drop_info = ark.dropLinker.getStageDrop(stage)
    drp_wname = {}
    for drop_type, game_id in drp:
        drop_name = getItemTag()['items'].get(game_id)['name']
        drop_id = ark.dropLinker.get(drop_name)
        drp_wname.update({drop_name: [drop_name, drop_id, drop_type]})
    for index in range(len(drop_info)):
        cur_drop: DropInfo = drop_info[index]
        if cur_drop.getVersion() != 1:
            continue
        if cur_drop.isEmpty():
            logger.warning(f"Find Empty Attack at Index:{index} in Stage:{stage},Set to None.")
            drop_info[index] = None
            continue
        new_drop = DropItemStack()
        ERR_G = [None, None, None]
        for type_, drp_li in cur_drop.dropList.items():
            for drp_name, drop_q in drp_li:
                new_drop.addItem(drp_name, drop_q, drp_wname.get(drp_name, ERR_G)[2] or 253)

        drop_info[index] = DropInfo(2, stage, cur_drop.attackTime, new_drop)
    # Write file Structure:([version \x02][len(droplist)<1>][[itemid<2>][quantity<2>][type<1>]]..[atk_time<3>][time<4>])
    # save raw file to backup
    os.rename(f"{DROPFOLDER_PATH}{stage}.drp", f"{DROPFOLDER_PATH}{stage}.drp.U12.{randomstr()}")
    ttl_upg = 0
    with open(f"{DROPFOLDER_PATH}{stage}.drp", 'wb') as fd:
        for dropstack in drop_info:
            if dropstack is None:
                continue
            fd.write(b'\x02')
            all_items = dropstack.dropList.getAllItems()
            fd.write(len(all_items).to_bytes(1, 'little'))
            for name, quantity, type_ in all_items:
                fd.write(ark.dropLinker.get(name).to_bytes(2, 'little'))
                fd.write(quantity.to_bytes(2, 'little'))
                fd.write((type_ + 1).to_bytes(1, 'little'))
            cost_time = dropstack.atk_in_t or 0
            try:
                fd.write(int(cost_time * 100).to_bytes(3, 'little'))
            except OverflowError:
                logger.warning(f"cannot convert cost_time({cost_time}) into byte!")
                fd.write(b'\xff\xff\xff')
            fd.write(dropstack.attackTime.to_bytes(4, 'little'))
            ttl_upg += 1
    logger.notice(f"Upgrade Finished![STAGE {stage},{ttl_upg}TUI]")
    return drop_info
Пример #17
0
def updateItemData():
    import requests
    from bs4 import BeautifulSoup as soup
    k = requests.get("http://prts.wiki/w/%E9%81%93%E5%85%B7%E4%B8%80%E8%A7%88")
    r = soup(k.content, "html.parser")
    item_dump = []
    for data in list(r.find_all(class_="smwdata")):
        item_dump.append([data.get("data-name"), data.get("data-rarity"), data.get("data-file"), data.get("data-id")])
    with open(".\\ArknightsGameData\\zh_CN\\gamedata\\excel\\item_table.json", "r", encoding="utf-8") as f:
        item = json.load(f)
    item_from_json = item["items"]
    item_names = {item_from_json.get(i)["name"]: item_from_json.get(i)["iconId"] for i in item_from_json.keys()}

    # for name, _, __, ___ in item_dump:
    #     try:
    #         item_names.remove(name)
    #     except ValueError:
    #         print(name)
    # print(item_names)
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE'
    }
    patch_item_name_data = {
        "合约赏金(旧)": "CRISIS_SHOP_COIN",
        "晶体电子单元": "MTL_SL_OEU",
        "寻访数据契约(遗愿焰火)": "LMTGS_COIN_601",
        "寻访数据契约(勿忘我)": "LMTGS_COIN_903",
        "寻访数据契约(地生五金)": "LMTGS_COIN_1401",
        "寻访数据契约(月隐晦明)": "LMTGS_COIN_1601",
        "α类新年寻访凭证(2020)": "2020recruitment10_1",
        "β类新年寻访凭证(2020)": "2020recruitment10_2",
        "γ类新年寻访凭证(2020)": "2020recruitment10_3",
        "α类新年寻访凭证(2021)": "2021recruitment10_1",
        "β类新年寻访凭证(2021)": "2021recruitment10_2",
        "γ类新年寻访凭证(2021)": "2021recruitment10_3",
    }
    _ = os.path
    _PARENT = _.realpath(_.join(_.dirname(__file__), '..'))
    unknown_item = []
    err_k = []
    for name, rarity, url, sortid in item_dump:
        # http://prts.wiki/images/thumb/2/23/%E9%81%93%E5%85%B7_%E5%B8%A6%E6%A1%86_%E6%97%A0%E5%90%8D%E7%9A%84%E8%AF%86%E5%88%AB%E7%89%8C.png/100px-%E9%81%93%E5%85%B7_%E5%B8%A6%E6%A1%86_%E6%97%A0%E5%90%8D%E7%9A%84%E8%AF%86%E5%88%AB%E7%89%8C.png
        # http://prts.wiki/images/2/23/%E9%81%93%E5%85%B7_%E5%B8%A6%E6%A1%86_%E6%97%A0%E5%90%8D%E7%9A%84%E8%AF%86%E5%88%AB%E7%89%8C.png
        # if image in current path,break
        try:
            id_ = item_names.get(name)
            if id_ is None:
                id_ = patch_item_name_data.get(name)
                if id_ is None:
                    id_ = name
                    unknown_item.append(id_)
                    logger.warning("[ItemIconUpdater]无效的材料转换名称:" + name)
            if os.path.exists(f"{_PARENT}\\imgReco\\img\\lootitem\\{id_}.png"):
                continue
            url_new = url.replace("/thumb", "")[::-1].split("/", 1)[1][::-1]
            rep = requests.get(url_new, headers=headers)
            if rep.status_code == 200:
                logger.notice(f"[ItemIconUpdater]完成图标更新: {id_}")
                with open(f"{_PARENT}\\imgReco\\img\\lootitem\\{id_}.png", "wb") as f:
                    f.write(rep.content)
        except:
            logger.error("出现错误:" + str([name, rarity, url, sortid]))
            err_k.append([name, rarity, url, sortid])
    print(unknown_item)
    print(err_k)
Пример #18
0
def recognizeEndItemsWithTag(ark, stageCode_or_dropList, quantity=True):
    def removeClosePos(gps: list):
        if len(gps) <= 1:
            return gps
        gps.sort()
        final = [gps[0]]
        prev_x = gps[0][0]
        for _x, _y in gps:
            if -7 < prev_x - _x < 7:
                continue
            prev_x = _x
            final.append((
                _x,
                _y,
            ))
        return final

    if isinstance(stageCode_or_dropList, str):
        drop_list = getDropList(stageCode_or_dropList)
    else:
        drop_list = stageCode_or_dropList
    for i in getActivityOpen()[1]:
        drop_list.add((i, getItemTag()['items'][i].get('name', "未知物品:" + i)))
    screen = ark.getScreenShot(470, 520, 800, 160)
    drop_reco = []
    for item, name in drop_list:
        dumped = False
        try:
            gps = ark.gameTemp.matchDifference(
                screen,
                cv2.resize(
                    ark.gameTemp.getTemplate("lootitem\\" + item + ".png")[0],
                    itemReco.STAGE_DROP)[29:29 + 46, 34:34 + 68],
                threshold=0.9)
        except cv2.error as cverr:
            try:
                gps = ark.gameTemp.matchDifference(
                    screen,
                    ark.gameTemp.getTemplate("lootitem\\dumped\\" + item +
                                             ".png")[0][29:29 + 46,
                                                        34:34 + 68],
                    threshold=0.9)
                dumped = True
            except (cv2.error, TypeError):
                logger.warning(
                    f"处理掉落物'{name}<{item}>'失败:(code={cverr.code}){cverr.err} in function '{cverr.func}'"
                )
                continue
        gps = removeClosePos(gps)
        for x, y in gps:
            if dumped:
                y = 28
            # 检测所有位置的掉落信息,分别根据不同位置判断不同掉落属性dropType
            num = -1
            x += 26
            y += 63
            if quantity:
                imgraw = Image.fromarray(screen[y:y + 27, x:x + 53])
                # cv2.imshow('r', np.array(imgraw))
                # cv2.waitKey(0)
                numimg = imgops.crop_blackedge2(imgraw, 150)
                # cv2.imshow('n', np.array(numimg))
                # cv2.waitKey(0)
                if numimg is None or numimg.size < (5, 5):
                    numimg = imgops.clear_background(imgraw, threshold=180)
                img = imgops.clear_background(numimg, threshold=120)
                # cv2.imshow('g', np.array(img))
                # cv2.waitKey(0)
                reco = ark.reconizerN.recognize2(img, subset="0123456789万")
                # print(reco)
                try:
                    num = int(reco[0]) if reco != '' else 0
                except:
                    num = 0
            else:
                num = -1
            err = num <= 0
            if err:
                logger.warning(f"识别到物品\"{name}\"数量出现异常({num}),已置零,该物品将不计入统计中")
            else:
                drop_reco.append({
                    "name": name,
                    "have": True,
                    "_acq": 0.9,
                    "type": recognizeEndItemDropType(screen, x),
                    "_pos": (x, y),
                    "quantity": num,
                    "error": err
                })
    return drop_reco
Пример #19
0
 def checkMapExist(self, name):
     if not self.hasMap(name.split('.', 1)[0]):
         logger.warning("不存在名为" + name.split('.', 1)[0] + "的Map")
         return False
     return True
Пример #20
0
    def readConfig(self,
                   config=None,
                   keepseek=False,
                   inner=False,
                   debug=False):
        # logger.system('<+>读取配置文件中...',flush=True)
        # TODO:处理空文件时异常:mrfzdata.mr ->list型数据
        # F = Config(cfgdata=json.load(open('.\MRFZdata\ArknightsGameData\excel\mission_table.json','rb')),Magic='mrfzd',file='mrfzdata2.mr')
        # D = Config(Magic='mrfzd',file='mrfzdata.mr')
        # R = Config(Magic='test',file='testcfg.t')
        # seek在mission->guide_1->unlockParam 166
        if config == None:
            config = self.cfg
        if self._fileopen:
            hand = self.data.tell()
        else:
            if hasattr(self, '_filename'):
                self.readFile(self._filename)
                hand = 0
            else:
                logger.error('<!>无可读取内容!配置不存在')
                return False
        if self._cfgread:
            self.cfg = configTree()
            config = self.cfg
        if self.checkHeader():
            self.version = struct.unpack('>f', self.readData(4))[0]
            if round(self.version,
                     1) < RootData.get("Config_version") and not inner:
                logger.error("<!>配置文件版本(%.1f)高于程序版本!无法读取" % self.version)
                return False
            elif round(self.version,
                       1) > RootData.get("Config_version") and not inner:
                logger.warning("<!>配置文件版本(%.1f)低于程序版本!保存时将使用当前版本存储配置!" %
                               self.version)
            if keepseek:
                self.data.seek(hand)
            _ts = time.time()
            if not inner:
                if self.readfromType(bool):
                    logger.error("<!>配置是空的!")
                    return False
                if debug is True:
                    logger.debug('<+>-----------ReadConfig-S-----------')
            while True:
                try:
                    name_len = struct.unpack('>h', self.readData(2))[0]  # 命名长度
                    name = self.readData(name_len).decode()
                    type_ = self.type(self.readData(1))

                    if not type_ == configTree:  # list? ---->item
                        value = self.readfromType(type_)
                        config.set(name, value)
                        if debug is True:
                            logger.debug('<+>[%s]%s.%s(%s): %s' %
                                         (self.data.tell(), config._root, name,
                                          name_len, str(type_)[8:-2:]))
                        if self.readfromType(bool):
                            if debug is True:
                                logger.debug('<+>[%s][t1]end,exit' %
                                             (self.data.tell()))
                            break
                    else:  # folder
                        config.addChild(name)
                        # ->
                        # empty folder ?
                        if self.readfromType(bool):
                            if debug is True:
                                logger.debug('<+>[%s][t2]end,exit' %
                                             (self.data.tell()))
                            break
                        # <-
                        self.readConfig(getattr(config, name),
                                        keepseek=True,
                                        inner=True,
                                        debug=debug)
                        if self.readfromType(bool):
                            if debug is True:
                                logger.debug('<+>[%s][t3]end,exit' %
                                             (self.data.tell()))
                            break
                        else:
                            self.data.seek(self.data.tell() - 1)
                except:
                    logger.error('<!>读取时出现错误 [seek:%s]' % self.data.tell())
                    # logger.system('<r>读取配置文件完成![用时%f秒]' % _ts)
                    return False
            _ts = time.time() - _ts
            if not inner:
                self._cfgread = True
                if debug is True:
                    logger.debug('<+>[%s]-----------ReadConfig-E-----------' %
                                 self.data.tell())
                logger.system('<+>读取配置文件完成![用时%.2f毫秒]' % (_ts * 1000))
            return True
        else:
            logger.error('<!>Magic Code不匹配!')
            return False