Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publish Python Module #24

Open
nestharus opened this issue Jan 25, 2024 · 3 comments
Open

Publish Python Module #24

nestharus opened this issue Jan 25, 2024 · 3 comments
Labels
enhancement New feature or request

Comments

@nestharus
Copy link

nestharus commented Jan 25, 2024

Can you publish this as a python module so that I can use it without cnping specific functions? It feels like I'm stealing your work.
Can you support accepting byte data for the json and sav data?
Can you decouple gvas from json_to_sav and sav_to_json stuff and have it take gvas byte data instead?
Can you not do any file i/o? If I want to write to or read from a file I want to do it myself. The root python scripts can be responsible for the file i/o =).

Thanks!

@nestharus
Copy link
Author

nestharus commented Jan 25, 2024

Here's an example of the gvas compression/decompression decoupled from the to_json/from_json stuff. Your code modified to be in dif functions :).

from typing import Union


def decompress_gvas(data: bytes) -> Union[None, tuple[bytes, int]]:
    uncompressed_len = int.from_bytes(data[0:4], byteorder='little')
    compressed_len = int.from_bytes(data[4:8], byteorder='little')
    magic_bytes = data[8:11]
    save_type = data[11]
    # Check for magic bytes
    if data[8:11] != b'PlZ':
        print(f'not a save, found {magic_bytes} instead of P1Z')
        return None
    # Valid save types
    if save_type not in [0x30, 0x31, 0x32]:
        print(f'unknown save type: {save_type}')
        return None
    # We only have 0x31 (single zlib) and 0x32 (double zlib) saves
    if save_type not in [0x31, 0x32]:
        print(f'unhandled compression type: {save_type}')
        return None
    if save_type == 0x31:
        # Check if the compressed length is correct
        if compressed_len != len(data) - 12:
            print(f'incorrect compressed length: {compressed_len}')
            return None
    # Decompress file
    uncompressed_data = zlib.decompress(data[12:])
    if save_type == 0x32:
        # Check if the compressed length is correct
        if compressed_len != len(uncompressed_data):
            print(f'incorrect compressed length: {compressed_len}')
            return None
        # Decompress file
        uncompressed_data = zlib.decompress(uncompressed_data)
    # Check if the uncompressed length is correct
    if uncompressed_len != len(uncompressed_data):
        print(f'incorrect uncompressed length: {uncompressed_len}')
        return None

    return uncompressed_data, save_type


def compress_gvas(data: bytes, save_type: int) -> bytes:
    uncompressed_len = len(data)
    compressed_data = zlib.compress(data)
    compressed_len = len(compressed_data)
    if save_type == 0x32:
        compressed_data = zlib.compress(compressed_data)

    # Create a byte array and append the necessary information
    result = bytearray()
    result.extend(uncompressed_len.to_bytes(4, byteorder='little'))
    result.extend(compressed_len.to_bytes(4, byteorder='little'))
    result.extend(b'PlZ')
    result.extend(bytes([save_type]))
    result.extend(compressed_data)

    return bytes(result)

@nestharus
Copy link
Author

nestharus commented Jan 25, 2024

Example of json<->gvas translation. Largely your code :)

def json_to_gvas(json_data, uesave_path="./lib/sav/uesave"):
    json_str = json.dumps(json_data)
    json_bytes = json_str.encode()

    uesave_run = subprocess.run(uesave_params_backward(uesave_path), input=json_bytes, capture_output=True)

    if uesave_run.returncode != 0:
        print(f'uesave.exe failed to convert to gvas (return {uesave_run.returncode})')
        return None

    return uesave_run.stdout


def gvas_to_json(gvas: bytes, uesave_path="./lib/sav/uesave"):
    uesave_run = subprocess.run(uesave_params_forward(uesave_path), input=gvas, capture_output=True)

    # Check if the command was successful
    if uesave_run.returncode != 0:
        print(f'uesave.exe failed to convert (return {uesave_run.returncode})')
        print(uesave_run.stdout.decode('utf-8'))
        print(uesave_run.stderr.decode('utf-8'))
        return None

    json_data = uesave_run.stdout
    json_data = json_data.decode()
    json_data = json.loads(json_data)

    return json_data

@cheahjs
Copy link
Owner

cheahjs commented Jan 25, 2024

I can look into publishing a module for some things, my current philosophy is to ensure that any scripts users run do not require any additional dependencies outside of Python.
This might wait until I can handle parsing without uesave-rs in the loop.

@cheahjs cheahjs added the enhancement New feature or request label Jan 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants