見出し画像

GVCReversion2の構造物ファイルを.nbt形式にするpythonコード


このコードについて

GVCReversion2の構造物ファイルを.nbt形式(ストラクチャーの形式)にするコードです(需要は知らん)
python初心者な上に適当な部分(# アイテムid変換用の部分とか)もあるので後で修正するかも
あと上の画像を見ればわかりますがピストンの向きだったり石のハーフブロックの種類とかが違ったりしてるので完璧な復元ではありません(やろうと思えば完璧にできると思うのでそのうち更新します(多分))

コード

# import
import glob
import tqdm
import os

# アイテムid変換用
color_item = ['wool', 'stained_glass', 'concrete', 'bed', 'carpet']
wood_item = ['fence', 'planks', 'log', 'leaves', 'fence_gate']
color = {0: 'white',1: 'orange',2: 'magenta',3: 'light_blue',4: 'yellow',5: 'lime',6: 'pink',7: 'gray',8: 'light_gray',9: 'cyan',10: 'purple',11: 'blue',12: 'brown',13: 'green',14: 'red',15: 'black'}
wood = {0: 'oak',1: 'spruce',2: 'birch',3: 'jungle',4: 'acacia',5: 'dark_oak',6: 'a',7: 'a',8: 'a',9: 'a',10: 'a',11: 'jungle',12: 'spruce',13: 'a',14: 'a',15: 'a',16: 'a'}
stone = {0: 'stone',1: 'granite',2: 'polished_granite',3: 'diorite',4: 'polished_diorite',5: 'andesite',6: 'polished_andesite'}
stone_bricks = {0: 'stone_bricks',1: 'mossy_stone_bricks',2: 'cracked_stone_bricks',3: 'chiseled_stone_bricks',4: 'stone_bricks'}
double_plant = {0: 'sunflower',1: 'lilac',2: 'tall_grass',3: 'large_fern',4: 'rose_bush',5: 'peony',10: 'tall_grass'}
others = {'skull': 'skeleton_skull','grass': 'grass_block','stone_slab': 'smooth_stone_slab','grass_path': 'dirt_path','yellow_flower': 'dandelion','hardened_clay': 'terracotta','brick_block': 'bricks','snow_layer': 'snow','snow': 'snow_block','lit_pumpkin': 'jack_o_lantern','lit_redstone_lamp': 'redstone_lamp','tilechest': 'chest','red_flower': 'poppy'}
#direction = {}

# リストとか作成
size_list_x = []
size_list_y = []
size_list_z = []
item_id_dic = {}
ignore_strings = ['gvc', 'mcdungeons', 'hmggirlfront']

# txtファイルのパス取得
path = './input/*.txt'
input_path = glob.glob(path)

# ファイル数取得
length = len(input_path)

# 1ファイルずつ読み込み
for i in range(length) :
    # ファイル開く
    txt_file = open(input_path[i])

    # 元ファイル名取得
    file_name = input_path[i].replace('./input/', '')

    # テキスト読み込み
    text = txt_file.readlines()
    text_read = [line for line in text if all(ignore not in line for ignore in ignore_strings)]

    # 変数作成
    count = 0
    dic_value = 0

    # 変換
    for data in tqdm.tqdm(text_read) :
        # いらない部分削除
        text_conversion = data.replace('Block,minecraft,', '').replace(',', '\n')

        # テキスト抽出
        element = text_conversion.splitlines()    # 一行ずつ分割
        item_id = element[0]
        block_x = element[1]
        block_y = element[2]
        block_z = element[3]
        block_state = element[4]

        # サイズ
        size_list_x.append(int(block_x))
        size_list_y.append(int(block_y))
        size_list_z.append(int(block_z))

        # アイテムidの変換
        if item_id in  color_item :
            item_id_output = color[int(block_state)] + '_' + item_id
        elif item_id in  wood_item :
            item_id_output = wood[int(block_state)] + '_' + item_id
        elif item_id == 'stone' :
            item_id_output = stone[int(block_state)]
        elif item_id == 'double_plant' :
            item_id_output = double_plant[int(block_state)]
        elif item_id == 'stonebrick' :
            item_id_output = stone_bricks[int(block_state)]
        elif item_id == 'stained_hardened_clay' :
            item_id_output = color[int(block_state)] + '_terracotta'
        elif item_id in others :
            item_id_output = others[item_id]
        else :
            item_id_output = item_id
    
        # palette用の辞書
        dic_check = str('minecraft:' + item_id_output) in item_id_dic
        if dic_check == False :
            item_id_dic['minecraft:' + str(item_id_output)] = dic_value
            dic_value += 1

        state = item_id_dic['minecraft:' + item_id_output]
        
        # 内容
        if count == 0 :
            blocks = '{pos: [' + str(block_x) + ',' + str(block_y) + ',' + str(block_z) + '],state: ' + str(state) + '}'
            palette = '{Name: "minecraft:' + item_id_output + '"}'
            count += 1
        else :
            blocks = blocks + ',{pos: [' + str(block_x) + ',' + str(block_y) + ',' + str(block_z) + '],state: ' + str(state) + '}'
        
            if dic_check == False :
                palette = palette + ',{Name: "minecraft:' + item_id_output + '"}'

    # サイズ
    size_x = max(size_list_x) + 1
    size_y = max(size_list_y) + 1
    size_z = max(size_list_z) + 1

    # テンプレ
    text_output = '{size: [' + str(size_x) + ',' + str(size_y) + ',' + str(size_z) + '],entities: [],blocks: [' + str(blocks) + '],palette: [' + str(palette) + '],DataVersion: 3578}'

    # ファイルの保存先指定
    output_dir = "output"

    # 出力
    with open(os.path.join(output_dir, file_name), "w") as output :
        output.write(str(text_output))

    # ファイル閉じる
    txt_file.close()

    # 変数をリセット
    size_list_x = []
    size_list_y = []
    size_list_z = []
    item_id_dic = {}
    blocks = ''
    palette = ''

    # 変換済みファイルは削除
    remove_path = str(txt_file).replace('<_io.TextIOWrapper name=\'', '').replace('\' mode=\'r\' encoding=\'utf-8\'>', '')
    # os.remove(remove_path)

    # 進捗
    progress = str(i + 1) + '/' + str(length) + ' completion(' + str(file_name) + ')'
    print(progress)

フォルダ構成について

適当なフォルダ
    ├input(フォルダ)
    ├output(フォルダ)
    └このコード.py

使い方

inputフォルダにGVCReversion2/assets/gvcr2/buildingの中のcamp.txtなどを入れてこのコードを実行するとoutputフォルダにcamp.txtが生成されます
生成されたファイルの中身をVS CodeにNBT Viewer(拡張機能)とかを入れた状態でコピペすると.nbtの形式になります
※tqdmをインストールしていない場合はインストールするかtqdmを使用しない形にしてください

更新履歴

2023/10/24
アイテムid変換の部分を少しコンパクトに

2023/10/26
重大なバグを修正←と思ったらできてなかったので修正中です←治ったかも?
最適化
全ファイル(63ファイル)を変換するのにかかっていた時間を470分→30分に(←?)(自分の環境で)


この記事が気に入ったらサポートをしてみませんか?