Created
March 20, 2022 19:45
-
-
Save maludwig/87ab60893330004bddddcec3d2f6a9d5 to your computer and use it in GitHub Desktop.
Timberborn World Lifter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
""" | |
Requires python 3 or higher | |
Usage: | |
This would lift a custom map, saved as "my_custom_map" by 8 blocks up vertically. | |
I doubt this will work with save files, but it should produce a new .timber file you can create a new game on | |
python --timber-path C:\Users\mitchell.ludwig\Documents\Timberborn\Maps\my_custom_map.timber --lift-by 8 | |
""" | |
from os import mkdir, path, makedirs | |
import json | |
import zipfile | |
import argparse | |
def extract_timber_file(timber_path: str): | |
dir_path = timber_path.replace('.timber', '') | |
with zipfile.ZipFile(timber_path, 'r') as zip_ref: | |
zip_ref.extractall(dir_path) | |
return dir_path | |
def compress_timber_file(dest_dir_path: str): | |
dest_timber_path = f"{dest_dir_path}.timber" | |
print(f"Writing new timber file here: {dest_timber_path}") | |
with zipfile.ZipFile(dest_timber_path, 'w', compression=zipfile.ZIP_DEFLATED) as zip_ref: | |
zip_ref.write(path.join(dest_dir_path, 'world.json'), 'world.json') | |
def lift_heights(height_str: str, lift_by: int): | |
new_heights = [] | |
for h in height_str.split(' '): | |
hn = int(h) | |
# print(f"{h} + 1 = {hn+1}") | |
new_heights.append(f"{int(h) + lift_by}") | |
return " ".join(new_heights) | |
def parse_args(): | |
parser = argparse.ArgumentParser(description='Lifts timberborn maps.') | |
parser.add_argument('--timber-path', type=str, default='HundredIslands.timber', help='the path to a .timber map file') | |
parser.add_argument('--lift-by', type=int, default=16, help='the number of blocks to lift the map by') | |
args = parser.parse_args() | |
return args | |
def lift_terrain(world_data, lift_by: int): | |
new_height_array_str = lift_heights(world_data['Singletons']['TerrainMap']['Heights']['Array'], lift_by) | |
world_data['Singletons']['TerrainMap']['Heights']['Array'] = new_height_array_str | |
def lift_entities(data, lift_by: int): | |
if isinstance(data, dict): | |
if "Coordinates" in data: | |
if "Z" in data["Coordinates"]: | |
data["Coordinates"]["Z"] = data["Coordinates"]["Z"] + lift_by | |
else: | |
for val in data.values(): | |
lift_entities(val, lift_by) | |
elif isinstance(data, list): | |
for val in data: | |
lift_entities(val, lift_by) | |
def main(): | |
args = parse_args() | |
dir_path = extract_timber_file(args.timber_path) | |
world_path = path.join(dir_path, 'world.json') | |
with open(world_path) as world_file: | |
data = json.load(world_file) | |
print(data['Singletons']['TerrainMap']['Heights']['Array']) | |
lift_terrain(data, args.lift_by) | |
lift_entities(data, args.lift_by) | |
dest_dir_path = f"{dir_path}_lift_{args.lift_by}" | |
makedirs(dest_dir_path, exist_ok=True) | |
dest_world_path = path.join(dest_dir_path, 'world.json') | |
with open(dest_world_path,'w') as lifted_file: | |
json.dump(data, lifted_file) | |
compress_timber_file(dest_dir_path) | |
print("Done!") | |
if __name__ == '__main__': | |
main() | |
else: | |
print(__name__) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment