PVirex Posted February 24, 2020 Share Posted February 24, 2020 (edited) Всем привет. Начало этой эпопеи можно прочитать тут, там же есть демо версия exe. Если кратко, это довольно простой инсталятор написанный на Python 3, но мне кажется будет работать и на 2 без особых переделок. Сам проект возник как шуточный, демонстративный, но со временем меня затянул и я решил доделать до конца, т.е до рабочего прототипа. Я в курсе, что есть более профильные решения, возможно даже проще, но у меня была цель сделать это на Python) Ссылка на репозиторий. Текущая версия: 2.1.0.0 Окружение: Python 3.8.1 wxPython pyinstaller pip install wxpython pip install pyinstaller Сложно понять, с чего начать) Пожалуй начну с самого начала, а именно mods_install.py т.к именно с него осуществляется запуск. В модуле содержится информация о панелях и инициализация самого приложения. Для добавления новой необходимо сделать импорт и внести в PANEL_INFO по примеру. В common расположены основные константы и пути, а также общие функции. constants.py # для отладки и запуска из IDE необходимо в root создать пустой файл start_python без расширения, это необходимо для поиска абстрактного пути ресурсов g_PYTHON_START = True if os.path.isfile(os.path.join(os.getcwd(), 'start_python')) else False # константа используется для включения записи логов в текстовый файл, см LOG_FOLDER в path.py g_DEBUG = True if os.path.isfile(os.path.join(os.getcwd(), 'debug')) else False # версия инсталятора VERSION = '2.0' # Имя рамки TITLE = 'My personal installer {}'.format(VERSION) # Очень важная константа!!! берется из version.xml игрового клиента, если версии не совпадут с клиентской, поставить моды не получится. VERSION_CLIENT = 'v.1.7.1.2' # размер фрейма и панели, панель чуть меньше из-за особенностей отрисовки wxWidget SIZE_FRAME = (600, 660) SIZE_PANEL = (585, 625) # стиль фрейма FRAME_STYLE = wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL | wx.BORDER # список папок которые будут удалены при выборе опции "Удалить кеш игры" пользователем DROP_GAME_FOLDER = ['battle_results', 'clan_cache', 'custom_data', 'veh_cmp_cache', 'dossier_cache', 'web_cache'] # список папок которые будут удалены при выборе опции "Удалить кеш модификаций" пользователем DROP_XVM_FOLDER = ['xvm\\Hitlog', 'xvm\\cache', 'xvm\\custom_data', 'xvm\\statistics'] DEFAULT_LANG = 'RU' # важная настройка, распаковывает моды не в конкретную папку, а как есть в корень игры. Это тнужно если в модпаке содержатся моды как mods так # и в res_mods SET_IN_GAME_FOLDER = True path.py ICON_PATH = resource_path('res_image\\main.ico') MAIN_LOGO_600x100_PATH = resource_path('res_image\\logo_600_100.png') MAIN_LOGO_600x500_PATH = resource_path('res_image\\logo_600x500.png') WGC_DEFAULT_PATH = os.path.join(os.environ['PROGRAMDATA'], 'Wargaming.net', 'GameCenter', 'preferences.xml') NOT_PATH_DEFAULT = resource_path('res_image\\not_found.jpg') # путь до кеша игры PATH_TO_CACHE_WOT = os.path.join(os.environ['appdata'], 'Wargaming.net', 'WorldOfTanks') LOG_FOLDER = os.path.join(os.environ['appdata'], 'TEMP_INSTALLER_LOGS', 'INSTALLER_LOGS') g_MODS_CONFIG = json.load(open(resource_path('mods_config.json'), encoding='utf-8')) g_PRESET_SETTINGS = json.load(open(resource_path('stream_settings.json'), encoding='utf-8')) PRESET_NAMES = list(g_PRESET_SETTINGS.keys()) В директории core расположены базовые класса и механики. Важным нюансом является то, что все ресурсы обязаны находиться в директории res, это больше обусловлено механизмом работы exe собранным с помощью pyinstaller. Для доступа к любому не py файлу должен осуществляться через функцию common_utils.resource_path def resource_path(relative_path): """ Функция для получения пути к ресурсам, все не .py файлы обязаны храниться в директории res. Такая зависимость обусловлена особенностями упаковки с помощью pyinstaller, т.к root меняется при запуске из .ехе """ if not g_PYTHON_START: base_path = sys._MEIPASS else: base_path = os.path.abspath(".") return os.path.join(base_path, 'res', relative_path) Конфиги. Самым важным безусловно является mods_config.json, такой формат выбран для простоты использования, описать можно вот так: { "P0LIROID Mods": { "checkBox": true, // флаг если для группы нужен именно чекбокс а не радиобуттон "Просмотр попадний в ангаре": [ // имя модификации в селекторе "res_image/battle_hits_poliroid.jpg", // относительный путь в ресурсах, обратить внимание что директорию res не учитываем "mods/battlehints_poliroid.zip", // относительный путь в ресурсах, до самого мода, обязательно архив zip "Текстовое описание, опционально, если не нужно то поставить null или пустую строку" ], "Менеджер реплеев": [ "res_image/replays_manager_poliroid.jpg", "mods/replays_manager.zip", "Текстовое описание, опционально, если не нужно то поставить null или пустую строку" ], "Кастомизация танков": [ "res_image/cust_veh.jpg", "mods/branding_vehicle.zip", null ] }, "Мои моды": [ "res_image/мой мод.jpg", "mods/мой мод.zip", null] ], "Radio button": { "Mods 1": [ "res_image/мой мод 1.jpg", "mods/мой мод1.zip", null], "Mods 2": [ "res_image/мой мод 2.jpg", "mods/мой мод2.zip", null] } } preset.json - устанавливает флажки для указанных групп, можно сделать сколько угодно пресетов. { "P0LIROID": [ "Просмотр попадний в ангаре", // просто добавляем имена модов как есть "Менеджер реплеев" ] } Модуль логирования logger.py имеет несколько уровней логирования: общий лог и только gui. Такой подход будет полезен в будущем если захочется использовать дополнительные библиотеки, которые тоже используют logger. Доступны следующие уровни: from core.logger import logger logger.info(msg) logger.debug(msg) logger.warning(msg) logger.error(msg) logger.exception(msg) try: pass exception Exception as e: logger.exception(e.msg) Основной UI который виден пользователю находится в step_panel. В текущий момент там 6 панелей: приветствие, поиск игры, выбор модификаций, подтверждение выбора, дополнительные настройки, установка. Возможно в будущем уделю больше внимания верстке и основной логике, в принципе там ничего сложного нет, если вы посвящены в начальные тайны ООП на Python. Сборка в ехе осуществляется либой pyinstaller. # -*- mode: python ; coding: utf-8 -*- import os block_cipher = None path_cwd = os.getcwd() a = Analysis(['mods_install.py'], pathex=['E:\\my_project\\mod_installer_stage_2'], # путь до проекта binaries=[], datas=[('res/locales/RU/LC_MESSAGES/ru.mo', 'res/locales/RU/LC_MESSAGES')], # локализации помещены отдельно специально hiddenimports=[], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False) # указываем относительный путь в проекте, полный путь до файла a.datas += [('res/res_image/battle_hits_poliroid.jpg', os.path.join(path_cwd, 'res', 'res_image', 'battle_hits_poliroid.jpg'), 'DATA')] a.datas += [('res/res_image/cust_veh.jpg', os.path.join(path_cwd, 'res', 'res_image', 'cust_veh.jpg'), 'DATA')] a.datas += [('res/res_image/logo_600_100.png', os.path.join(path_cwd, 'res', 'res_image', 'logo_600_100.png'), 'DATA')] a.datas += [('res/res_image/logo_600x500.png', os.path.join(path_cwd, 'res', 'res_image', 'logo_600x500.png'), 'DATA')] a.datas += [('res/res_image/not_found.jpg', os.path.join(path_cwd, 'res', 'res_image', 'not_found.jpg'), 'DATA')] a.datas += [('res/res_image/replays_manager_poliroid.jpg', os.path.join(path_cwd, 'res', 'res_image', 'replays_manager_poliroid.jpg'), 'DATA')] a.datas += [('res/res_image/main.ico', os.path.join(path_cwd, 'res', 'res_image', 'main.ico'), 'DATA')] a.datas += [('res/mods_config.json', os.path.join(path_cwd, 'res', 'mods_config.json'), 'DATA')] a.datas += [('res/stream_settings.json', os.path.join(path_cwd, 'res', 'stream_settings.json'), 'DATA')] a.datas += [('res/mods/battlehints_poliroid.zip', os.path.join(path_cwd, 'res', 'mods', 'battlehints_poliroid.zip'), 'DATA')] a.datas += [('res/mods/branding_vehicle.zip', os.path.join(path_cwd, 'res', 'mods', 'branding_vehicle.zip'), 'DATA')] a.datas += [('res/mods/replays_manager.zip', os.path.join(path_cwd, 'res', 'mods', 'replays_manager.zip'), 'DATA')] pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE(pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name='Name EXE', debug=True, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=False, # если поставить True, то приложение будет запускаться с консолью, иногда удобно для отладки icon=os.path.join(path_cwd, 'res\\res_image\\main.ico')) Для сборки запустить build.bat Edited April 22, 2020 by PVirex 3 @ Quote Link to comment Short link Share on other sites More sharing options...
PVirex Posted February 24, 2020 Author Share Posted February 24, 2020 (edited) Сборка исполняемого файла Коммитом от on Mar 5, 2020 добавил парсинг mods_config.json в mods_install.spec Таким образом, конечному пользователю нет необходимости вносить правки в mods_install.spec, что может плохо закончиться. Теперь все ресурсы берутся из конфига автоматически и запаковываются. Для сборки необходимо: Шаг 1: установить python и либы, можно использовать setup.bat Шаг 2: занести нужные моды в конфиг mods_config.json Шаг 3: запустить сборщик 9 апреля, добавил упаковку модов в zip из директории mods_unpack. Это повышает удобство при пересборке модпака, достаточно хранить все необходимые моды в таком виде, как они должны находиться в клиенте игры. Например: replays/mods/1.8.0.2/replays.wotmod battlehints/res_mods/1.8.0.2/scripts/client/gui/mods/mod_battlehints.pyc После запуска батника в директории: res/mods появятся архивы с названием корневой папки и полной вложенностью как в оригинале replays.zip и battlehints.zip. Останется только внести zip архивы в mods_config.json Edited April 9, 2020 by PVirex @ Quote Link to comment Short link Share on other sites More sharing options...
PVirex Posted February 24, 2020 Author Share Posted February 24, 2020 (edited) 2.0.1 * убрана необходимость вносить ресурсы в main.spec 2.0.2.0 * добавлено сохранение в кеш последнего указанного пути и последних установленных модификаций 2.0.3.0 * добавил упаковку модов в zip из директории mods_unpack. Это повышает удобство при пересборке модпака, достаточно хранить все необходимые моды в таком виде, как они должны находиться в клиенте игры. При этом моды у которых не совпадает версия папки для модов с той, что в клиенте добавляться не будут 2.1.0.0 * добавлена поддержка локализаций с сохранением выбора в кеш Edited April 22, 2020 by PVirex @ Quote Link to comment Short link Share on other sites More sharing options...
StranikS_Scan Posted February 24, 2020 Share Posted February 24, 2020 Это типа установщик модов, написанный на пайтоне, с компиляцией exe через wxPython? @ Quote Link to comment Short link Share on other sites More sharing options...
PVirex Posted February 24, 2020 Author Share Posted February 24, 2020 (edited) 5 минут назад, StranikS_Scan сказал: Это типа установщик модов, написанный на пайтоне, с компиляцией exe через wxPython? Наоборот немного, инсталятор модификаций написанный на Python с помощью wxPython и запакованный в ехе с помощью pyinstaller Edited February 24, 2020 by PVirex 1 @ Quote Link to comment Short link Share on other sites More sharing options...
tunut Posted March 23, 2020 Share Posted March 23, 2020 (edited) а оно работает ?:\ все скачал, установил, скомпилировал без ошибок - а кнопка Далее (после выбора папки) не активна Edited March 23, 2020 by tunut 1 @ Quote Link to comment Short link Share on other sites More sharing options...
PVirex Posted March 25, 2020 Author Share Posted March 25, 2020 (edited) 23.03.2020 в 11:54, tunut сказал: а оно работает ?:\ все скачал, установил, скомпилировал без ошибок - а кнопка Далее (после выбора папки) не активна Скрыть содержимое Должно работать. Обрати внимание на версию клиентав constants.py, текущая версия на проде вот такая VERSION_CLIENT = 'v.1.8.0.1' Извини за долгий ответ, мне казалось никому не интересно и я не стал дописывать мануал Обнови бранч, я внес правки и поправил версию. Edited March 25, 2020 by PVirex @ Quote Link to comment Short link Share on other sites More sharing options...
tunut Posted March 25, 2020 Share Posted March 25, 2020 49 минут назад, PVirex сказал: Обрати внимание на версию клиентав constants.py, конечно поменял, если версия клиента не правильная - выводится соответствующее сообщение а тут ничего, просто кнопка не активна @ Quote Link to comment Short link Share on other sites More sharing options...
PVirex Posted March 25, 2020 Author Share Posted March 25, 2020 (edited) @tunut а WGC стоит? или ты выбираешь путь до игры руками? мб и баг у меня где-то))) я воспроизвел, это баг. ты не используешь WGC. Поправлю минут через 10-20. Спаисбо за инфу Edited March 25, 2020 by PVirex @ Quote Link to comment Short link Share on other sites More sharing options...
tunut Posted March 25, 2020 Share Posted March 25, 2020 5 минут назад, PVirex сказал: WGC стоит? стоит, но запускаю его только при обновлении клиента, а так запускаю через ехе-шник игру @ Quote Link to comment Short link Share on other sites More sharing options...
PVirex Posted March 25, 2020 Author Share Posted March 25, 2020 (edited) @tunut значит стоит не по стандартному пути, не в programdata. Я поправил, должна кнопка теперь разблокироваться при ручном выборе пути. Fixed at head revision Edited March 25, 2020 by PVirex @ Quote Link to comment Short link Share on other sites More sharing options...
tunut Posted March 25, 2020 Share Posted March 25, 2020 21 минуту назад, PVirex сказал: Я поправил, должна кнопка теперь разблокироваться при ручном выборе пути. так и есть, спс а зафиксировать тултип к левому или правому краю установщика можно? что-б не гулял за мышкой... а то бесит. @ Quote Link to comment Short link Share on other sites More sharing options...
PVirex Posted March 25, 2020 Author Share Posted March 25, 2020 @tunut оххх, это тултип отдельная боль и страдания. Я не нашел нормального решения как сделать тултип для three и начал колхозить сам) вышло то, что есть. По идее, мне кажестся можно зафиксировать его справа или слева, но тут есть трудности, я подумаю что можно сделать. Не забудьте поделиться ссылкой на Ваш модпак, очень интересно, что вышло в оконечном результате. У меня есть планы на доработку) 2 @ Quote Link to comment Short link Share on other sites More sharing options...
ktulho Posted March 25, 2020 Share Posted March 25, 2020 Наверняка потребуется возможность выбора языка установки. @ Quote Link to comment Short link Share on other sites More sharing options...
PVirex Posted March 25, 2020 Author Share Posted March 25, 2020 (edited) 1 минуту назад, ktulho сказал: Наверняка потребуется возможность выбора языка установки. было в планах на будущее как и кеш, есть даже отработанная технология Edited March 25, 2020 by PVirex @ Quote Link to comment Short link Share on other sites More sharing options...
PVirex Posted April 7, 2020 Author Share Posted April 7, 2020 Добавил кеш, теперь сохраняется последний указанный путь и выбранные модификации 2 @ Quote Link to comment Short link Share on other sites More sharing options...
PVirex Posted April 9, 2020 Author Share Posted April 9, 2020 Добавил упаковку модов в zip из директории mods_unpack. Это повышает удобство при пересборке модпака, достаточно хранить все необходимые моды в таком виде, как они должны находиться в клиенте игры. При этом моды у которых не совпадает версия папки для модов с той, что в клиенте добавляться не будут 3 @ Quote Link to comment Short link Share on other sites More sharing options...
PVirex Posted April 22, 2020 Author Share Posted April 22, 2020 25.03.2020 в 16:35, ktulho сказал: Наверняка потребуется возможность выбора языка установки. Добавлена поддержка локализаций: RU, EN Выбирается 1 раз при первом запуске и сохраняется в кеш. Для переопределения снести кеш или поменять/удалить ключ 'language' 3 @ Quote Link to comment Short link Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.