File size: 4,297 Bytes
630a44b
0e32057
 
630a44b
af81d86
 
a17fa67
4be4e7c
a17fa67
 
 
 
 
 
 
ad523a8
4be4e7c
 
 
 
 
ad523a8
 
4be4e7c
 
ad523a8
4be4e7c
 
 
 
 
 
 
 
 
 
 
ad523a8
4be4e7c
a17fa67
4be4e7c
af81d86
 
 
a17fa67
 
 
 
 
 
 
 
 
 
 
 
 
4be4e7c
630a44b
fcf7884
af81d86
 
 
a17fa67
af81d86
 
4be4e7c
 
 
af81d86
 
 
 
 
 
 
 
4be4e7c
af81d86
 
fcf7884
4be4e7c
af81d86
a17fa67
 
 
 
 
af81d86
4be4e7c
af81d86
fcf7884
 
af81d86
 
fcf7884
af81d86
fcf7884
 
 
af81d86
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import gradio as gr
import fanl_yp
import zlib

def load_and_display_info(gameFilePath: str):
    """Загружает файл и возвращает game.title + game объект для дальнейшей обработки"""
    if gameFilePath is None:
        return "", "", gr.update(interactive=False), gr.update(visible=False)
    
    try:
        with open(gameFilePath, "rb") as f:
            compressed_data = f.read()
        data = zlib.decompress(compressed_data)
        game = fanl_yp.decode.decode(data)
        title = getattr(game, 'title', 'Название не найдено')
        
        # Генерация списка removable lock IDs
        indexOffset = getattr(game, 'indexOffset', 0)
        removable_locks = []
        offset = indexOffset
        
        for objectContainer in game.objectContainers:
            if objectContainer.headerReader.hasVoxels():
                removable_locks.append(f"{offset} {objectContainer.name}")
            offset += 1
            
        if removable_locks:
            locks_html = "<div style='background-color: #f0f0f0; padding: 10px; border-radius: 5px;'>"
            locks_html += f"<h4>Removable lock IDs (IndexOffset: {indexOffset}):</h4>"
            locks_html += "<ul>"
            for lock in removable_locks:
                locks_html += f"<li>{lock}</li>"
            locks_html += "</ul></div>"
        else:
            locks_html = "<div style='background-color: #f0f0f0; padding: 10px; border-radius: 5px;'>" \
                        f"<h4>Removable lock IDs (IndexOffset: {indexOffset}):</h4>" \
                        "<p>Нет доступных элементов для удаления</p></div>"
        
        return title, locks_html, gr.update(interactive=True), gr.update(visible=True)
    except Exception as e:
        return f"Ошибка загрузки файла: {str(e)}", "", gr.update(interactive=False), gr.update(visible=False)

def process_save_file(game_obj, original_path: str):
    """Обрабатывает сохранение и возвращает путь к новому файлу"""
    if game_obj is None or original_path is None:
        return None
    
    try:
        output_path = original_path + "_fixed"
        output = fanl_yp.encode.encode(game_obj, output_path)
        output.flush()
        return output_path
    except Exception as e:
        raise gr.Error(f"Ошибка обработки файла: {str(e)}")

def clear_handler():
    """Обработчик очистки файла"""
    return "", "", gr.update(interactive=False), gr.update(visible=False)

with gr.Blocks() as demo:
    gr.Markdown("## Обработка сохранений игры")

    with gr.Row():
        file_input = gr.File(label="Загрузите файл сохранения", file_types=None)

    title_output = gr.Textbox(label="Информация о сохранении", interactive=False)
    
    # HTML компонент для отображения списка removable lock IDs
    locks_output = gr.HTML(visible=False)

    process_button = gr.Button("Обработать сохранение", interactive=False)
    
    file_output = gr.File(label="Сохранить исправленный файл")

    # Скрытое состояние для хранения объекта game между вызовами
    game_state = gr.State()

    # Когда файл загружен — обновляем текстовое поле и разблокируем кнопку
    file_input.upload(
        fn=load_and_display_info,
        inputs=file_input,
        outputs=[title_output, locks_output, process_button, locks_output],
        queue=False
    )

    # Когда файл удален — очищаем все поля и блокируем кнопку
    file_input.clear(
        fn=clear_handler,
        inputs=None,
        outputs=[title_output, locks_output, process_button, locks_output],
        queue=False
    )

    # При нажатии кнопки запускаем обработку
    process_button.click(
        fn=process_save_file,
        inputs=[game_state, file_input],
        outputs=file_output
    )

if __name__ == "__main__":
    demo.launch()