Skip to content
This repository has been archived by the owner on Jul 11, 2023. It is now read-only.

Commit

Permalink
Add support for 7zip archives. Add new mod and more documentation for…
Browse files Browse the repository at this point in the history
… the new requirements
  • Loading branch information
remyroy committed Feb 15, 2016
1 parent 2e14a29 commit c5850da
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 44 deletions.
7 changes: 4 additions & 3 deletions BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ CDDA Game Launcher is developed using Python. In order to run or build the launc

## Requirements

The full list of requirements is available in [requirements.txt](requirements.txt). Most of these requirements are Python packages that can be installed using [pip](https://en.wikipedia.org/wiki/Pip_%28package_manager%29). Unfortunately, there is no easy to use and easy to install build tools on Windows to compile and install a few of these requirements:
The full list of requirements is available in [requirements.txt](requirements.txt). Most of these requirements are Python packages that can be installed using [pip](https://en.wikipedia.org/wiki/Pip_%28package_manager%29). Unfortunately, some of these requirements need build tools which are not easy to use nor easy to install on Windows. Here are those special requirements:

* PyQt5
* scandir
* lxml
* pylzma

I suggest you download and install already compiled binaries for these. At this time of writing, [the PyQt5 binaries](https://www.riverbankcomputing.com/software/pyqt/download5) are only available for Python 3.4 which means you should be using that version of Python as well.

Compiled binaries for lxml and scandir can be found on [Christoph Gohlke's Unofficial Windows Binaries](http://www.lfd.uci.edu/~gohlke/pythonlibs/). If you are using Python 3.5+, scandir should already be included.
Compiled binaries for lxml, scandir and pylzma can be found on [Christoph Gohlke's Unofficial Windows Binaries](http://www.lfd.uci.edu/~gohlke/pythonlibs/). If you are using Python 3.5+, scandir should already be included.

## Running the launcher

Expand All @@ -32,7 +33,7 @@ The resulting launcher executable should be in the `dist` directory.
* By default, Python 3.4 is installed in `C:\Python34`. To setup your PATH, type `set PATH=%PATH%;C:\Python34;C:\Python34\Scripts` in your command line window and press `↵ Enter`.
3. Install most requirements by typing the following `pip` command in your command line window: `pip install SQLAlchemy alembic PyInstaller html5lib cssselect arrow rarfile` and press `↵ Enter`.
4. Download and install the PyQt5 binaries from [Riverbank Computing's website](https://www.riverbankcomputing.com/software/pyqt/download5). Make sure to download the same platform version (either 32-bit or 64-bit). It should match the same platform version you got in Step 1.
5. Download and install the scandir and lxml packages from [Christoph Gohlke's Unofficial Windows Binaries](http://www.lfd.uci.edu/~gohlke/pythonlibs/). It should match the same Python version and platform version you got in Step 1. `cp34` means CPython 3.4, `win32` means 32-bit and `win_amd64` means 64-bit in Christoph Gohlke's packages naming convention. To install `.whl` packages from Christoph Gohlke's Unofficial Windows Binaries page, you can using pip. In your command line window, type: `pip install [path to .whl]` and press `↵ Enter`.
5. Download and install the scandir, the lxml and the pylzma packages from [Christoph Gohlke's Unofficial Windows Binaries](http://www.lfd.uci.edu/~gohlke/pythonlibs/). It should match the same Python version and platform version you got in Step 1. `cp34` means CPython 3.4, `win32` means 32-bit and `win_amd64` means 64-bit in Christoph Gohlke's packages naming convention. To install `.whl` packages from Christoph Gohlke's Unofficial Windows Binaries page, you can using pip. In your command line window, type: `pip install [path to .whl]` and press `↵ Enter`.
6. Download the CDDA Game Launcher source code. If you have git installed, you can type the following command in your command line window: `git clone https://github.com/remyroy/CDDA-Game-Launcher.git`. You can also download the source code from [https://github.com/remyroy/CDDA-Game-Launcher/archive/master.zip](https://github.com/remyroy/CDDA-Game-Launcher/archive/master.zip). Make sure to extract the zip file somewhere before trying to run the code.
7. In your command line window, change directory to the source code directory. Type `cd [path to source code]` and press `↵ Enter`.
8. See if you can run the launcher by typing the following command in your command line window: `python cddagl\launcher.py` and press `↵ Enter`. If you have everything setuped correctly, you should see the launcher running.
Expand Down
141 changes: 101 additions & 40 deletions cddagl/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from urllib.parse import urljoin, urlencode

import rarfile
from py7zlib import Archive7z, NoPasswordGivenError, FormatError

from distutils.version import LooseVersion

Expand Down Expand Up @@ -3682,7 +3683,14 @@ def size_query_finished(self):

content_length = int(self.http_reply.rawHeader(b'Content-Length'))
self.current_repo_info['size'] = content_length
self.size_le.setText(sizeof_fmt(content_length))

selection_model = self.repository_lv.selectionModel()
if selection_model is not None and selection_model.hasSelection():
selected = selection_model.currentIndex()
selected_info = self.repo_soundpacks[selected.row()]

if selected_info is self.current_repo_info:
self.size_le.setText(sizeof_fmt(content_length))
else:
selection_model = self.repository_lv.selectionModel()
if selection_model is not None and selection_model.hasSelection():
Expand Down Expand Up @@ -3852,6 +3860,10 @@ def __init__(self):
self.downloading_new_mod = False
self.extracting_new_mod = False

self.install_type = None
self.extracting_file = None
self.extracting_zipfile = None

self.close_after_install = False

self.game_dir = None
Expand Down Expand Up @@ -4262,32 +4274,51 @@ def install_new(self):
status_bar.showMessage('Testing downloaded file '
'archive')

if self.downloaded_file.lower().endswith('.zip'):
archive_class = zipfile.ZipFile
archive_exception = zipfile.BadZipFile
test_method = 'testzip'
elif self.downloaded_file.lower().endswith('.rar'):
archive_class = rarfile.RarFile
archive_exception = rarfile.BadRarFile
test_method = 'testrar'

try:
with archive_class(self.downloaded_file) as z:
test = getattr(z, test_method)
if test() is not None:
status_bar.clearMessage()
status_bar.showMessage(
'Downloaded archive is invalid')

self.finish_install_new_mod()
return
except archive_exception:
status_bar.clearMessage()
status_bar.showMessage('Selected file is a bad '
'archive file')
if self.downloaded_file.lower().endswith('.7z'):
try:
with open(self.downloaded_file, 'rb') as f:
archive = Archive7z(f)
except FormatError:
status_bar.clearMessage()
status_bar.showMessage('Selected file is a bad '
'archive file')

self.finish_install_new_mod()
return
self.finish_install_new_mod()
return
except NoPasswordGivenError:
status_bar.clearMessage()
status_bar.showMessage('Selected file is a '
'password protected archive file')

self.finish_install_new_mod()
return
else:
if self.downloaded_file.lower().endswith('.zip'):
archive_class = zipfile.ZipFile
archive_exception = zipfile.BadZipFile
test_method = 'testzip'
elif self.downloaded_file.lower().endswith('.rar'):
archive_class = rarfile.RarFile
archive_exception = rarfile.BadRarFile
test_method = 'testrar'

try:
with archive_class(self.downloaded_file) as z:
test = getattr(z, test_method)
if test() is not None:
status_bar.clearMessage()
status_bar.showMessage(
'Downloaded archive is invalid')

self.finish_install_new_mod()
return
except archive_exception:
status_bar.clearMessage()
status_bar.showMessage('Selected file is a bad '
'archive file')

self.finish_install_new_mod()
return

status_bar.clearMessage()
self.extract_new_mod()
Expand All @@ -4309,10 +4340,12 @@ def install_new(self):

self.extracting_new_mod = False

self.extracting_zipfile.close()
if self.extracting_zipfile is not None:
self.extracting_zipfile.close()

download_dir = os.path.dirname(self.downloaded_file)
retry_rmtree(download_dir)
if self.install_type == 'direct_download':
download_dir = os.path.dirname(self.downloaded_file)
retry_rmtree(download_dir)

if os.path.isdir(self.extract_dir):
retry_rmtree(self.extract_dir)
Expand Down Expand Up @@ -4458,21 +4491,28 @@ def download_dl_progress(self, bytes_read, total_bytes):
def extract_new_mod(self):
self.extracting_new_mod = True

if self.downloaded_file.lower().endswith('.zip'):
archive_class = zipfile.ZipFile
elif self.downloaded_file.lower().endswith('.rar'):
archive_class = rarfile.RarFile
if self.downloaded_file.lower().endswith('.7z'):
self.extracting_zipfile = open(self.downloaded_file, 'rb')
self.extracting_archive = Archive7z(self.extracting_zipfile)

z = archive_class(self.downloaded_file)
self.extracting_zipfile = z
self.extracting_infolist = self.extracting_archive.getmembers()
else:
if self.downloaded_file.lower().endswith('.zip'):
archive_class = zipfile.ZipFile
elif self.downloaded_file.lower().endswith('.rar'):
archive_class = rarfile.RarFile

z = archive_class(self.downloaded_file)
self.extracting_zipfile = z

self.extracting_infolist = z.infolist()

self.extract_dir = os.path.join(self.game_dir, 'newmod')
while os.path.exists(self.extract_dir):
self.extract_dir = os.path.join(self.game_dir,
'newmod-{0}'.format('%08x' % random.randrange(16**8)))
os.makedirs(self.extract_dir)

self.extracting_infolist = z.infolist()
self.extracting_index = 0

main_window = self.get_main_window()
Expand Down Expand Up @@ -4510,6 +4550,10 @@ def timeout():
self.extracting_new_mod = False

self.extracting_zipfile.close()
self.extracting_zipfile = None

if self.downloaded_file.lower().endswith('.7z'):
self.extracting_archive = None

if self.install_type == 'direct_download':
download_dir = os.path.dirname(self.downloaded_file)
Expand All @@ -4520,11 +4564,21 @@ def timeout():
else:
extracting_element = self.extracting_infolist[
self.extracting_index]

self.extracting_label.setText('Extracting {0}'.format(
extracting_element.filename))

self.extracting_zipfile.extract(extracting_element,
self.extract_dir)

if self.downloaded_file.lower().endswith('.7z'):
destination = os.path.join(self.extract_dir,
*extracting_element.filename.split('/'))
dest_dir = os.path.dirname(destination)
if not os.path.isdir(dest_dir):
os.makedirs(dest_dir)
with open(destination, 'wb') as f:
f.write(extracting_element.read())
else:
self.extracting_zipfile.extract(extracting_element,
self.extract_dir)

self.extracting_index += 1

Expand Down Expand Up @@ -4767,7 +4821,14 @@ def size_query_finished(self):

content_length = int(self.http_reply.rawHeader(b'Content-Length'))
self.current_repo_info['size'] = content_length
self.size_le.setText(sizeof_fmt(content_length))

selection_model = self.repository_lv.selectionModel()
if selection_model is not None and selection_model.hasSelection():
selected = selection_model.currentIndex()
selected_info = self.repo_soundpacks[selected.row()]

if selected_info is self.current_repo_info:
self.size_le.setText(sizeof_fmt(content_length))
else:
selection_model = self.repository_lv.selectionModel()
if selection_model is not None and selection_model.hasSelection():
Expand Down
11 changes: 11 additions & 0 deletions data/mods.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@
"expected_filename": "Guns Equipment Mods Expansion Mode v1.5 experimental.rar",
"homepage": "http://smf.cataclysmdda.com/index.php?topic=11823.0"
},
{
"type": "browser_download",
"ident": "jury_rigged_robots",
"name": "Jury-Rigged Robots",
"description": "Options for salvaging, jury rigging, and reprogramming broken robots.",
"author": "Sunshine",
"size": 10625,
"url": "https://mega.co.nz/#!rQkklSKQ!l_2XXv7YtnK8On668dqHH-MKA5THufUulGoXr-YRvjA",
"expected_filename": "Jury_Rigged_Robots.7z",
"homepage": "http://smf.cataclysmdda.com/index.php?topic=10667.0"
},
{
"type": "browser_download",
"ident": "Remove_Nether",
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ lxml
cssselect
arrow
scandir
rarfile
rarfile
pylzma

0 comments on commit c5850da

Please sign in to comment.