defplayer_inventory_search(data_file): defsearch_shulker_box_item(shulker_box): if"Items"notin shulker_box["tag"]["BlockEntityTag"]: return for item in shulker_box["tag"]["BlockEntityTag"]["Items"]: count_item(item["id"], int(item["Count"])) print(item["id"], " ", item["Count"])
target_file = nbtlib.load(data_file)
for i in target_file["Inventory"]: count_item(i["id"], int(i["Count"])) print(i["id"], " ", int(i["Count"])) ifstr(i["id"]).endswith("shulker_box") and"tag"in i: search_shulker_box_item(i)
for i in target_file["EnderItems"]: count_item(i["id"], int(i["Count"])) print(i["id"], " ", int(i["Count"])) ifstr(i["id"]).endswith("shulker_box") and"tag"in i: search_shulker_box_item(i)
试着跑一下,看起来效果不错
看来玩家数据这一块算是搞腚力 (~o ̄3 ̄)~
区域文件
Minecraft 的 .mca 区域文件其实是由多个区块组成,每个区块以 NBT 标签的形式储存
也就是说,同样可以用 NBT 编辑器查看区域文件
众所周知,游戏中容器其实属于一个方块实体,所以很容易就能得知要查看哪个标签
所需的方块实体标签如下
1 2 3 4
Chunk [x, y] in world at (x, y): ├── block_entities: │ └── ... └── ...
for i inrange(0, 32): for j inrange(0, 32): chunk = anvil.Chunk.from_region(target_region, i, j) if chunk.tile_entities: te = chunk.tile_entities for k in te: if"Items"notin k: continue for a in k["Items"]: count_item(a["id"], int(str(a["Count"]))) # print(a["id"], " ", a["Count"]) ifstr(a["id"]).endswith("shulker_box") and"tag"in a: search_shulker_box_item(a)
哎,不错不错,这个脚本的核心就差不多写完了
不过,在尝试几次之后就发现了异常,抛了个 IndexError
通过编辑器打开有问题的文件看看,似乎时文件本身就有点问题
管那么多干嘛,直接 except 就完事了 = ̄ω ̄=
不久后又有个异常
1
anvil.errors.ChunkNotFound: Could not find chunk (0, 0)
try: for i inrange(0, 32): for j inrange(0, 32): try: chunk = anvil.Chunk.from_region(target_region, i, j) if chunk.tile_entities: te = chunk.tile_entities for k in te: if"Items"notin k: continue for a in k["Items"]: count_item(a["id"], int(str(a["Count"]))) # print(a["id"], " ", a["Count"]) ifstr(a["id"]).endswith("shulker_box") and"tag"in a: search_shulker_box_item(a) except ChunkNotFound: pass except IndexError as e: print(f"{e}, when searching region {region_file}")
... ... # 记录输出部分 withopen(fr'{PATH_OUTDIR}\results.csv', 'w', encoding='utf8', newline='') as out: writer = csv.writer(out) writer.writerow(["item", "count"]) for i in item_record.items(): writer.writerow(list(i))
defmain(): # 检查路径,路径有问题就报错 ifnot os.path.isdir(PATH_OUTDIR): raise NotADirectoryError("the outdirectory specified is not a directory")
# 检查文件是否为存档 if"level.dat"notin os.listdir(PATH_WORLD): raise FileNotFoundError("file: level.dat cannot be found in the world directory!")
# 几个连续的搜索尝试 try: print(r"searching \playerdata") for f in os.listdir(fr"{PATH_WORLD}\playerdata"): if f.endswith(".dat"): player_inventory_search(fr"{PATH_WORLD}\playerdata\{f}") except FileNotFoundError: print(r"directory: \playerdata cannot be found in the world directory")
try: print(r"searching \region") for f in os.listdir(fr"{PATH_WORLD}\region"): if f.endswith(".mca"): region_search(fr"{PATH_WORLD}\region\{f}") except FileNotFoundError: print(r"directory: \region cannot be found in the world directory")
try: print(r"searching \DIM1\region") for f in os.listdir(fr"{PATH_WORLD}\DIM1\region"): if f.endswith(".mca"): region_search(fr"{PATH_WORLD}\DIM1\region\{f}") except FileNotFoundError: print(r"directory: \DIM1\region cannot be found in the world directory")
try: print(r"searching \DIM-1\region") for f in os.listdir(fr"{PATH_WORLD}\DIM-1\region"): if f.endswith(".mca"): region_search(fr"{PATH_WORLD}\DIM-1\region\{f}") except FileNotFoundError: print(r"directory: \DIM-1\region cannot be found in the world directory")
# 文件输出 withopen(fr'{PATH_OUTDIR}\results.csv', 'w', encoding='utf8', newline='') as out: writer = csv.writer(out) writer.writerow(["item", "count"]) for i in item_record.items(): writer.writerow(list(i))
try: for i inrange(0, 32): for j inrange(0, 32): try: chunk = anvil.Chunk.from_region(target_region, i, j) if chunk.tile_entities: te = chunk.tile_entities for k in te: if"Items"notin k: continue for a in k["Items"]: count_item(a["id"], int(str(a["Count"]))) # print(a["id"], " ", a["Count"]) ifstr(a["id"]).endswith("shulker_box") and"tag"in a: search_shulker_box_item(a) except ChunkNotFound: pass except IndexError as e: print(f"{e}, when searching region {region_file}")
defplayer_inventory_search(data_file): defsearch_shulker_box_item(shulker_box): if"Items"notin shulker_box["tag"]["BlockEntityTag"]: return for item in shulker_box["tag"]["BlockEntityTag"]["Items"]: count_item(item["id"], int(item["Count"])) # print(item["id"], " ", item["Count"])
target_file = nbtlib.load(data_file)
for i in target_file["Inventory"]: count_item(i["id"], int(i["Count"])) # print(i["id"], " ", int(i["Count"])) ifstr(i["id"]).endswith("shulker_box") and"tag"in i: search_shulker_box_item(i)
for i in target_file["EnderItems"]: count_item(i["id"], int(i["Count"])) # print(i["id"], " ", int(i["Count"])) ifstr(i["id"]).endswith("shulker_box") and"tag"in i: search_shulker_box_item(i)
defmain(): ifnot os.path.isdir(PATH_OUTDIR): raise NotADirectoryError("the outdirectory specified is not a directory")
if"level.dat"notin os.listdir(PATH_WORLD): raise FileNotFoundError("file: level.dat cannot be found in the world directory!")
try: print(r"searching \playerdata") for f in os.listdir(fr"{PATH_WORLD}\playerdata"): if f.endswith(".dat"): player_inventory_search(fr"{PATH_WORLD}\playerdata\{f}") except FileNotFoundError: print(r"directory: \playerdata cannot be found in the world directory")
try: print(r"searching \region") for f in os.listdir(fr"{PATH_WORLD}\region"): if f.endswith(".mca"): region_search(fr"{PATH_WORLD}\region\{f}") except FileNotFoundError: print(r"directory: \region cannot be found in the world directory")
try: print(r"searching \DIM1\region") for f in os.listdir(fr"{PATH_WORLD}\DIM1\region"): if f.endswith(".mca"): region_search(fr"{PATH_WORLD}\DIM1\region\{f}") except FileNotFoundError: print(r"directory: \DIM1\region cannot be found in the world directory")
try: print(r"searching \DIM-1\region") for f in os.listdir(fr"{PATH_WORLD}\DIM-1\region"): if f.endswith(".mca"): region_search(fr"{PATH_WORLD}\DIM-1\region\{f}") except FileNotFoundError: print(r"directory: \DIM-1\region cannot be found in the world directory")
# print(item_record)
withopen(fr'{PATH_OUTDIR}\results.csv', 'w', encoding='utf8', newline='') as out: writer = csv.writer(out) writer.writerow(["item", "count"]) for i in item_record.items(): writer.writerow(list(i))