Перейти к содержимому
Zone of Games Forum

Рекомендованные сообщения

Where Winds Meet

header.jpg

  • Метки: Открытый мир, Бесплатная игра, Экшен, Ролевой экшен, Для нескольких игроков
  • Платформы: PC XS PS5
  • Разработчик: Everstone Studio
  • Издатель: NetEase Games
  • Дата выхода: 14 ноября 2025 года
  • Отзывы Steam: 8347 отзывов, 77% положительных
Where Winds Meet - это эпическая приключенческая ролевая игра с открытым миром Wuxia, действие которой разворачивается в Древнем Китае в десятом веке. Игрокам предстоит взять на себя роль молодого мастера меча и отправиться в путешествие, чтобы раскрыть тайны собственной личности. Позвольте ветру унести вашу легенду в эпическое путешествие на Восток!
Скриншоты
1.jpg2.jpg3.jpg4.jpg
  • Лайк (+1) 3

Поделиться сообщением


Ссылка на сообщение

очень при очень кривой перевод , и ладно если бы где то английские были слова, так там иероглифы (((лучше пока что чисто на английском поторчать!

Поделиться сообщением


Ссылка на сообщение

Классная у Китая технология, если кто стримы смотрел, налету будто переводит, налету копируется в “translate_words_map_en (переименован)” и сразу кодируется. Странные они люди, они знают как у них закодирован файл, но всё равно по-человечески сделать не могли, чтобы хотя бы не было китайских иероглифов.

Поделиться сообщением


Ссылка на сообщение

Есть у кого возможно открыть файл через https://atom-editor.cc/ или Sublime Text или Visual Studio Code (VS Code) ? Notepad++ как-то не особо справляется...

Изменено пользователем Develuk

Поделиться сообщением


Ссылка на сообщение

На просторах интернета найден скрипт для распаковки в .dat, далее текст вытаскивается без проблем.

Скрытый текст

import re
import os
import struct
import pyzstd
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QTextEdit, QVBoxLayout, QHBoxLayout, QFileDialog, QLabel
from PyQt5.QtCore import Qt, QThread, pyqtSignal


def extract_patch_file(input_file, output_dir, log_callback):
    try:
        base_name = os.path.splitext(os.path.basename(input_file))[0]
        output_subdir = os.path.join(output_dir, base_name)
        os.makedirs(output_subdir, exist_ok=True)

        with open(input_file, 'rb') as f:
            if f.read(4) != b'\xEF\xBE\xAD\xDE':
                return False

            f.read(4)  # Skip version
            offset_count_bytes = f.read(4)
            offset_count = struct.unpack('<I', offset_count_bytes)[0]
            f.read(4)  # Skip padding

            if offset_count == 1:
                comp_block_len = struct.unpack('<I', f.read(4))[0]
                comp_block = f.read(comp_block_len)

                if len(comp_block) < comp_block_len:
                    return False

                header = comp_block[:9]
                comp_data_part = comp_block[9:]

                if len(header) < 9:
                    return False

                comp_type, comp_size, decomp_size = struct.unpack('<BII', header)

                if comp_type == 0x04:
                    try:
                        decomp_data = pyzstd.decompress(comp_data_part)
                        output_path = os.path.join(output_subdir, f"{base_name}_0.dat")
                        with open(output_path, 'wb') as out_f:
                            out_f.write(decomp_data)
                        log_callback(f"{base_name}_0.dat {comp_block_len} {decomp_size}")
                    except Exception:
                        pass
            else:
                offsets = [struct.unpack('<I', f.read(4))[0] for _ in range(offset_count)]
                data_start = f.tell()

                for i in range(offset_count - 1):
                    current_offset = offsets[i]
                    next_offset = offsets[i + 1]
                    block_len = next_offset - current_offset

                    f.seek(data_start + current_offset)
                    comp_block = f.read(block_len)

                    if len(comp_block) < block_len:
                        continue

                    if len(comp_block) < 9:
                        continue

                    header = comp_block[:9]
                    comp_data_part = comp_block[9:]
                    comp_type, comp_size, decomp_size = struct.unpack('<BII', header)

                    if comp_type == 0x04:
                        try:
                            decomp_data = pyzstd.decompress(comp_data_part)
                            output_path = os.path.join(output_subdir, f"{base_name}_{i}.dat")
                            with open(output_path, 'wb') as out_f:
                                out_f.write(decomp_data)
                            log_callback(f"{os.path.basename(output_path)} {current_offset} {decomp_size}")
                        except Exception:
                            pass

            return True

    except Exception:
        return False


class WorkerThread(QThread):
    log_signal = pyqtSignal(str)

    def __init__(self, input_path, output_dir):
        super().__init__()
        self.input_path = input_path
        self.output_dir = output_dir

    def run(self):
        if os.path.isdir(self.input_path):
            for filename in os.listdir(self.input_path):
                full_path = os.path.join(self.input_path, filename)
                if os.path.isfile(full_path):
                    extract_patch_file(full_path, self.output_dir, self.log_signal.emit)
        elif os.path.isfile(self.input_path):
            extract_patch_file(self.input_path, self.output_dir, self.log_signal.emit)


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Where_winds_meet_data_Extractor")
        self.setGeometry(100, 100, 800, 600)
        self.init_ui()

    def init_ui(self):
        layout = QVBoxLayout()

        button_layout = QHBoxLayout()

        # Select File Button
        self.select_file_btn = QPushButton("Select File")
        select_file_label = QLabel("选择文件")
        select_file_label.setAlignment(Qt.AlignCenter)
        select_file_label.setStyleSheet("font-size: 10px; color: gray;")
        file_box = QVBoxLayout()
        file_box.addWidget(self.select_file_btn)
        file_box.addWidget(select_file_label)

        # Select Folder Button
        self.select_folder_btn = QPushButton("Select Folder")
        select_folder_label = QLabel("选择文件夹")
        select_folder_label.setAlignment(Qt.AlignCenter)
        select_folder_label.setStyleSheet("font-size: 10px; color: gray;")
        folder_box = QVBoxLayout()
        folder_box.addWidget(self.select_folder_btn)
        folder_box.addWidget(select_folder_label)

        # Output Folder Button
        self.output_folder_btn = QPushButton("Output Folder")
        output_folder_label = QLabel("输出文件夹")
        output_folder_label.setAlignment(Qt.AlignCenter)
        output_folder_label.setStyleSheet("font-size: 10px; color: gray;")
        output_box = QVBoxLayout()
        output_box.addWidget(self.output_folder_btn)
        output_box.addWidget(output_folder_label)

        # Start Processing Button
        self.start_btn = QPushButton("Start Processing")
        start_label = QLabel("开始处理")
        start_label.setAlignment(Qt.AlignCenter)
        start_label.setStyleSheet("font-size: 10px; color: gray;")
        start_box = QVBoxLayout()
        start_box.addWidget(self.start_btn)
        start_box.addWidget(start_label)

        # Merge Files Button
        self.merge_btn = QPushButton("Merge Files")
        merge_label = QLabel("合并文件")
        merge_label.setAlignment(Qt.AlignCenter)
        merge_label.setStyleSheet("font-size: 10px; color: gray;")
        merge_box = QVBoxLayout()
        merge_box.addWidget(self.merge_btn)
        merge_box.addWidget(merge_label)

        # Add buttons to layout
        button_layout.addLayout(file_box)
        button_layout.addLayout(folder_box)
        button_layout.addLayout(output_box)
        button_layout.addLayout(start_box)
        button_layout.addLayout(merge_box)

        layout.addLayout(button_layout)

        self.log_box = QTextEdit()
        self.log_box.setReadOnly(True)
        layout.addWidget(self.log_box)

        self.setLayout(layout)

        self.input_path = None
        self.output_dir = None

        # Connect buttons
        self.select_file_btn.clicked.connect(self.select_input_file)
        self.select_folder_btn.clicked.connect(self.select_input_folder)
        self.output_folder_btn.clicked.connect(self.select_output_dir)
        self.start_btn.clicked.connect(self.start_processing)
        self.merge_btn.clicked.connect(self.merge_dat_files)

    def log(self, message):
        self.log_box.append(message)

    def select_input_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "Select Patch File")
        if file_path:
            self.input_path = file_path
            self.log(f"Selected input file: {file_path}")

    def select_input_folder(self):
        folder_path = QFileDialog.getExistingDirectory(self, "Select Input Folder")
        if folder_path:
            self.input_path = folder_path
            self.log(f"Selected input folder: {folder_path}")

    def select_output_dir(self):
        folder_path = QFileDialog.getExistingDirectory(self, "Select Output Folder")
        if folder_path:
            self.output_dir = folder_path
            self.log(f"Selected output folder: {folder_path}")

    def start_processing(self):
        if not self.input_path:
            self.log("Please select input file or folder")
            return
        if not self.output_dir:
            self.log("Please select output folder")
            return

        self.worker = WorkerThread(self.input_path, self.output_dir)
        self.worker.log_signal.connect(self.log)
        self.worker.start()

    def merge_dat_files(self):
        folder_path = QFileDialog.getExistingDirectory(self, "Select Folder to Merge .dat Files")
        if not folder_path:
            return
    
        output_file = os.path.join(folder_path, "merged_output.bin")
    
        try:
            files = [f for f in os.listdir(folder_path) if f.endswith('.dat')]
    
            def extract_number(filename):
                match = re.search(r'(\d+)\.dat$', filename)
                return int(match.group(1)) if match else float('inf')
            files.sort(key=extract_number)
    
            with open(output_file, 'wb') as outfile:
                for filename in files:
                    file_path = os.path.join(folder_path, filename)
                    with open(file_path, 'rb') as infile:
                        outfile.write(infile.read())
                    self.log(f"Merged: {filename}")
    
            self.log(f"✅ Merging completed. Output saved to: {output_file}")
        except Exception as e:
            self.log(f"❌ Error during merging: {str(e)}")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

 

 

Поделиться сообщением


Ссылка на сообщение
Только что, Pavelstop сказал:

На просторах интернета найден скрипт для распаковки в .dat, далее текст вытаскивается без проблем.

  Код (Показать содержимое)


import re
import os
import struct
import pyzstd
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QTextEdit, QVBoxLayout, QHBoxLayout, QFileDialog, QLabel
from PyQt5.QtCore import Qt, QThread, pyqtSignal


def extract_patch_file(input_file, output_dir, log_callback):
    try:
        base_name = os.path.splitext(os.path.basename(input_file))[0]
        output_subdir = os.path.join(output_dir, base_name)
        os.makedirs(output_subdir, exist_ok=True)

        with open(input_file, 'rb') as f:
            if f.read(4) != b'\xEF\xBE\xAD\xDE':
                return False

            f.read(4)  # Skip version
            offset_count_bytes = f.read(4)
            offset_count = struct.unpack('<I', offset_count_bytes)[0]
            f.read(4)  # Skip padding

            if offset_count == 1:
                comp_block_len = struct.unpack('<I', f.read(4))[0]
                comp_block = f.read(comp_block_len)

                if len(comp_block) < comp_block_len:
                    return False

                header = comp_block[:9]
                comp_data_part = comp_block[9:]

                if len(header) < 9:
                    return False

                comp_type, comp_size, decomp_size = struct.unpack('<BII', header)

                if comp_type == 0x04:
                    try:
                        decomp_data = pyzstd.decompress(comp_data_part)
                        output_path = os.path.join(output_subdir, f"{base_name}_0.dat")
                        with open(output_path, 'wb') as out_f:
                            out_f.write(decomp_data)
                        log_callback(f"{base_name}_0.dat {comp_block_len} {decomp_size}")
                    except Exception:
                        pass
            else:
                offsets = [struct.unpack('<I', f.read(4))[0] for _ in range(offset_count)]
                data_start = f.tell()

                for i in range(offset_count - 1):
                    current_offset = offsets[i]
                    next_offset = offsets[i + 1]
                    block_len = next_offset - current_offset

                    f.seek(data_start + current_offset)
                    comp_block = f.read(block_len)

                    if len(comp_block) < block_len:
                        continue

                    if len(comp_block) < 9:
                        continue

                    header = comp_block[:9]
                    comp_data_part = comp_block[9:]
                    comp_type, comp_size, decomp_size = struct.unpack('<BII', header)

                    if comp_type == 0x04:
                        try:
                            decomp_data = pyzstd.decompress(comp_data_part)
                            output_path = os.path.join(output_subdir, f"{base_name}_{i}.dat")
                            with open(output_path, 'wb') as out_f:
                                out_f.write(decomp_data)
                            log_callback(f"{os.path.basename(output_path)} {current_offset} {decomp_size}")
                        except Exception:
                            pass

            return True

    except Exception:
        return False


class WorkerThread(QThread):
    log_signal = pyqtSignal(str)

    def __init__(self, input_path, output_dir):
        super().__init__()
        self.input_path = input_path
        self.output_dir = output_dir

    def run(self):
        if os.path.isdir(self.input_path):
            for filename in os.listdir(self.input_path):
                full_path = os.path.join(self.input_path, filename)
                if os.path.isfile(full_path):
                    extract_patch_file(full_path, self.output_dir, self.log_signal.emit)
        elif os.path.isfile(self.input_path):
            extract_patch_file(self.input_path, self.output_dir, self.log_signal.emit)


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Where_winds_meet_data_Extractor")
        self.setGeometry(100, 100, 800, 600)
        self.init_ui()

    def init_ui(self):
        layout = QVBoxLayout()

        button_layout = QHBoxLayout()

        # Select File Button
        self.select_file_btn = QPushButton("Select File")
        select_file_label = QLabel("选择文件")
        select_file_label.setAlignment(Qt.AlignCenter)
        select_file_label.setStyleSheet("font-size: 10px; color: gray;")
        file_box = QVBoxLayout()
        file_box.addWidget(self.select_file_btn)
        file_box.addWidget(select_file_label)

        # Select Folder Button
        self.select_folder_btn = QPushButton("Select Folder")
        select_folder_label = QLabel("选择文件夹")
        select_folder_label.setAlignment(Qt.AlignCenter)
        select_folder_label.setStyleSheet("font-size: 10px; color: gray;")
        folder_box = QVBoxLayout()
        folder_box.addWidget(self.select_folder_btn)
        folder_box.addWidget(select_folder_label)

        # Output Folder Button
        self.output_folder_btn = QPushButton("Output Folder")
        output_folder_label = QLabel("输出文件夹")
        output_folder_label.setAlignment(Qt.AlignCenter)
        output_folder_label.setStyleSheet("font-size: 10px; color: gray;")
        output_box = QVBoxLayout()
        output_box.addWidget(self.output_folder_btn)
        output_box.addWidget(output_folder_label)

        # Start Processing Button
        self.start_btn = QPushButton("Start Processing")
        start_label = QLabel("开始处理")
        start_label.setAlignment(Qt.AlignCenter)
        start_label.setStyleSheet("font-size: 10px; color: gray;")
        start_box = QVBoxLayout()
        start_box.addWidget(self.start_btn)
        start_box.addWidget(start_label)

        # Merge Files Button
        self.merge_btn = QPushButton("Merge Files")
        merge_label = QLabel("合并文件")
        merge_label.setAlignment(Qt.AlignCenter)
        merge_label.setStyleSheet("font-size: 10px; color: gray;")
        merge_box = QVBoxLayout()
        merge_box.addWidget(self.merge_btn)
        merge_box.addWidget(merge_label)

        # Add buttons to layout
        button_layout.addLayout(file_box)
        button_layout.addLayout(folder_box)
        button_layout.addLayout(output_box)
        button_layout.addLayout(start_box)
        button_layout.addLayout(merge_box)

        layout.addLayout(button_layout)

        self.log_box = QTextEdit()
        self.log_box.setReadOnly(True)
        layout.addWidget(self.log_box)

        self.setLayout(layout)

        self.input_path = None
        self.output_dir = None

        # Connect buttons
        self.select_file_btn.clicked.connect(self.select_input_file)
        self.select_folder_btn.clicked.connect(self.select_input_folder)
        self.output_folder_btn.clicked.connect(self.select_output_dir)
        self.start_btn.clicked.connect(self.start_processing)
        self.merge_btn.clicked.connect(self.merge_dat_files)

    def log(self, message):
        self.log_box.append(message)

    def select_input_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "Select Patch File")
        if file_path:
            self.input_path = file_path
            self.log(f"Selected input file: {file_path}")

    def select_input_folder(self):
        folder_path = QFileDialog.getExistingDirectory(self, "Select Input Folder")
        if folder_path:
            self.input_path = folder_path
            self.log(f"Selected input folder: {folder_path}")

    def select_output_dir(self):
        folder_path = QFileDialog.getExistingDirectory(self, "Select Output Folder")
        if folder_path:
            self.output_dir = folder_path
            self.log(f"Selected output folder: {folder_path}")

    def start_processing(self):
        if not self.input_path:
            self.log("Please select input file or folder")
            return
        if not self.output_dir:
            self.log("Please select output folder")
            return

        self.worker = WorkerThread(self.input_path, self.output_dir)
        self.worker.log_signal.connect(self.log)
        self.worker.start()

    def merge_dat_files(self):
        folder_path = QFileDialog.getExistingDirectory(self, "Select Folder to Merge .dat Files")
        if not folder_path:
            return
    
        output_file = os.path.join(folder_path, "merged_output.bin")
    
        try:
            files = [f for f in os.listdir(folder_path) if f.endswith('.dat')]
    
            def extract_number(filename):
                match = re.search(r'(\d+)\.dat$', filename)
                return int(match.group(1)) if match else float('inf')
            files.sort(key=extract_number)
    
            with open(output_file, 'wb') as outfile:
                for filename in files:
                    file_path = os.path.join(folder_path, filename)
                    with open(file_path, 'rb') as infile:
                        outfile.write(infile.read())
                    self.log(f"Merged: {filename}")
    
            self.log(f"✅ Merging completed. Output saved to: {output_file}")
        except Exception as e:
            self.log(f"❌ Error during merging: {str(e)}")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

 

 

Ахах, это я на форуме у ребят спрашивал как раз про распаковку файла

И мне в ответ скинули этот скрипт ))
 

  • Лайк (+1) 1

Поделиться сообщением


Ссылка на сообщение

Вот сделал скрипт на Python`е Яндекс.Диск для распаковки файлов translate_words_map. Пока на что время хватило. Как раз переделал сверху, но он умеет распаковывать и собирать обратно

Изменено пользователем suncrash66
  • Лайк (+1) 2

Поделиться сообщением


Ссылка на сообщение

как сделал я , взял оригинальный translate_words_map_en его переименовал в translate_words_map_zh_cn и заменил в папке HD\oversea\locale. потом взял переведённый translate_words_map_de и его переименовал в translate_words_map_en. закинул тоже в папку. Теперь если слова не хватает он превращает его в Английский, а не в китайский . 
 

image.png?ex=691d9adb&is=691c495b&hm=791

Изменено пользователем MultiArhat
  • Лайк (+1) 2

Поделиться сообщением


Ссылка на сообщение
41 минуту назад, suncrash66 сказал:

Вот сделал скрипт на Python`е Яндекс.Диск для распаковки файлов translate_words_map. Пока на что время хватило. Как раз переделал сверху, но он умеет распаковывать и собирать обратно

Это все же QT оказалась) Я вчера в лаунчере обнаружил qm файлы) Думаю надо в эту область копать) правда ушел спать) Игра же вроде на Qt framework...

Изменено пользователем DOG729
  • Лайк (+1) 1

Поделиться сообщением


Ссылка на сообщение

На скорую руку скрипт достающий из dat файлов из прошлого скрипта текст.Нужно дорабатывать,но результат есть.Так же по ссылке пример того что получается,из файла Лагофаста.

https://disk.yandex.ru/d/gTZFZZX6oOHIQw

Поделиться сообщением


Ссылка на сообщение

пользуясь случаем хочу передать привет всем девушкам ,кто пользуется процессорами ryzen.

Поделиться сообщением


Ссылка на сообщение
15 минут назад, Мих@лыч сказал:

На скорую руку скрипт достающий из dat файлов из прошлого скрипта текст.Нужно дорабатывать,но результат есть.Так же по ссылке пример того что получается,из файла Лагофаста.

https://disk.yandex.ru/d/gTZFZZX6oOHIQw

OFFSET=8728

LENGTH=24345

 

Проблема в том что в данном случае мы привязаны к длине текста. Нужно реверсить бинарную таблицу
чтоб получить `id → text` 

 

Поделиться сообщением


Ссылка на сообщение
8 минут назад, DOG729 сказал:

OFFSET=8728

LENGTH=24345

 

Проблема в том что в данном случае мы привязаны к длине текста. Нужно реверсить бинарную таблицу
чтоб получить `id → text` 

 

Согласен.Это больше для посмотреть что там вообще есть.

Поделиться сообщением


Ссылка на сообщение
2 минуты назад, Мих@лыч сказал:

Согласен.Это больше для посмотреть что там вообще есть.

В этом не было нужды можно было просто файл вскрыть в txt редакторе и со скролить в низ))

Поделиться сообщением


Ссылка на сообщение

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас

  • Похожие публикации

    • Автор: AltRA
      Absolute Drift

      Метки: Гонки, Открытый мир, Вождение, Физика, Сложная Платформы: PC XONE PS4 SW iOS An MAC LIN Разработчик: Funselektor Labs, FlippFly Издатель: Funselektor Labs Серия: Funselektor Labs Inc. Дата выхода: 29 июля 2015 года Отзывы Steam: 2126 отзывов, 89% положительных
    • Автор: toga
      Avernum 4: Greed and Glory

      Метки: Ролевая игра, Глубокий сюжет, Стратегия, Приключение, Партийная ролевая игра Разработчик: Spiderweb Software Издатель: Spiderweb Software Дата выхода: 22.10.2025 Отзывы Steam: 66 отзывов, 95% положительных


Zone of Games © 2003–2025 | Реклама на сайте.

×