From 9005de76d9ca93bc69219ad2fffaaf24021537a4 Mon Sep 17 00:00:00 2001 From: MagicBot Date: Fri, 16 Oct 2026 13:43:40 -0400 Subject: [PATCH] Number output files and folders instead of overwriting Pack now writes .cache, or .cache.1, .2, ... if that file already exists (replaces the fixed .cache.new name). Unpack writes each target folder under ARCANE_DUMP the same way, e.g. COBJECTS.1. The output folder is created only after the cache loads, so a missing cache does not leave an empty numbered folder. Co-Authored-By: Claude Opus 5.5 --- mbEditorPro2.0/arcane/util/ArcFileCache.py | 15 ++++ mbEditorPro2.0/arcane/util/__init__.py | 2 +- mbEditorPro2.0/mbEditorPro.py | 88 +++++++++++----------- 3 files changed, 60 insertions(+), 45 deletions(-) diff --git a/mbEditorPro2.0/arcane/util/ArcFileCache.py b/mbEditorPro2.0/arcane/util/ArcFileCache.py index 9b94758..5a6a682 100644 --- a/mbEditorPro2.0/arcane/util/ArcFileCache.py +++ b/mbEditorPro2.0/arcane/util/ArcFileCache.py @@ -6,6 +6,7 @@ # Magicbane Emulator Project © 2013 - 2022 # www.magicbane.com +import os import struct import zlib @@ -81,7 +82,21 @@ def write_bytes(cache_file, value): cache_file.write(value) +def next_available_path(path): + # Returns path if unused, otherwise the first free path.1, path.2, ... + if not os.path.exists(path): + return path + + index = 1 + while os.path.exists(f'{path}.{index}'): + index += 1 + + return f'{path}.{index}' + + def save_cache_file(filename, resources, compress=True): + filename = next_available_path(filename) + print('Packing to ' + filename) cache_file = open(filename, 'wb') num_resources = len(resources) diff --git a/mbEditorPro2.0/arcane/util/__init__.py b/mbEditorPro2.0/arcane/util/__init__.py index fc303b6..6b98bd3 100644 --- a/mbEditorPro2.0/arcane/util/__init__.py +++ b/mbEditorPro2.0/arcane/util/__init__.py @@ -6,5 +6,5 @@ # Magicbane Emulator Project © 2013 - 2022 # www.magicbane.com -from .ArcFileCache import load_cache_file, save_cache_file +from .ArcFileCache import load_cache_file, save_cache_file, next_available_path from .ResStream import ResStream diff --git a/mbEditorPro2.0/mbEditorPro.py b/mbEditorPro2.0/mbEditorPro.py index 181316d..3a14150 100644 --- a/mbEditorPro2.0/mbEditorPro.py +++ b/mbEditorPro2.0/mbEditorPro.py @@ -89,6 +89,14 @@ EDITOR_TARGETS = [ ] +def create_unpack_directory(base_directory): + # Never unpack over an existing folder; use the next free numbered name. + directory = next_available_path(base_directory) + os.makedirs(directory) + print('Unpacking to ' + directory) + return directory + + def init_cobjects(): for obj_type in COBJECTS_MAP: directory_path = os.path.join(COBJECTS_DIRECTORY, OBJECT_TYPE_TO_STRING[obj_type]) @@ -146,9 +154,11 @@ def init_render(): def unpack_cobjects(): - init_cobjects() - resources = load_cache_file('CObjects.cache') + directory = create_unpack_directory(COBJECTS_DIRECTORY) + + for obj_type in COBJECTS_MAP: + os.makedirs(os.path.join(directory, OBJECT_TYPE_TO_STRING[obj_type])) with tqdm(total=len(resources)) as pBar: for res_id, data in resources: @@ -158,7 +168,7 @@ def unpack_cobjects(): arc_in = COBJECTS_MAP[obj_type]() filepath = os.path.join( - COBJECTS_DIRECTORY, + directory, OBJECT_TYPE_TO_STRING[obj_type], f'{res_id:d}.json' ) @@ -193,7 +203,7 @@ def pack_cobjects(): resources.append([res_id, out_stream.get_bytes()]) - save_cache_file('CObjects.cache.new', resources) + save_cache_file('CObjects.cache', resources) def test_cobjects(): @@ -221,16 +231,15 @@ def test_cobjects(): def unpack_czones(): - init_czones() - resources = load_cache_file('CZone.cache') + directory = create_unpack_directory(CZONE_DIRECTORY) with tqdm(total=len(resources)) as pBar: for res_id, data in resources: arc_zone = ArcZone() in_stream = ResStream(data) filepath = os.path.join( - CZONE_DIRECTORY, + directory, f'{res_id:d}.json' ) arc_zone.load_binary(in_stream) @@ -257,7 +266,7 @@ def pack_czones(): resources.append([res_id, out_stream.get_bytes()]) - save_cache_file('CZone.cache.new', resources) + save_cache_file('CZone.cache', resources) def test_czones(): @@ -280,16 +289,15 @@ def test_czones(): def unpack_sound(): - init_sound() - resources = load_cache_file('Sound.cache') + directory = create_unpack_directory(SOUND_DIRECTORY) with tqdm(total=len(resources)) as pBar: for res_id, data in resources: arc_sound = ArcSound() in_stream = ResStream(data) filepath = os.path.join( - SOUND_DIRECTORY, + directory, f'{res_id:d}.wav' ) @@ -319,7 +327,7 @@ def pack_sound(): resources.append([res_id, out_stream.get_bytes()]) - save_cache_file('Sound.cache.new', resources, False) + save_cache_file('Sound.cache', resources, False) def test_sound(): @@ -350,16 +358,15 @@ def test_sound(): def unpack_texture(): - init_texture() - print('Decompressing Texture Cache...') resources = load_cache_file('Textures.cache') + directory = create_unpack_directory(TEXTURE_DIRECTORY) print('Writing images') with tqdm(total=len(resources)) as pBar: for res_id, data in resources: filepath = os.path.join( - TEXTURE_DIRECTORY, + directory, f'{res_id:d}.tga' ) @@ -386,7 +393,7 @@ def pack_texture(): resources.append([res_id, out_stream.get_bytes()]) - save_cache_file('Textures.cache.new', resources) + save_cache_file('Textures.cache', resources) def test_texture(): @@ -418,14 +425,13 @@ def test_texture(): def unpack_terrain(): - init_terrain() - resources = load_cache_file('TerrainAlpha.cache') + directory = create_unpack_directory(TERRAIN_DIRECTORY) with tqdm(total=len(resources)) as pBar: for res_id, data in resources: filepath = os.path.join( - TERRAIN_DIRECTORY, + directory, f'{res_id:d}.tga' ) @@ -452,7 +458,7 @@ def pack_terrain(): resources.append([res_id, out_stream.get_bytes()]) - save_cache_file('TerrainAlpha.cache.new', resources) + save_cache_file('TerrainAlpha.cache', resources) def test_terrain(): @@ -486,16 +492,15 @@ def test_terrain(): def unpack_mesh(): - init_mesh() - resources = load_cache_file('Mesh.cache') + directory = create_unpack_directory(MESH_DIRECTORY) with tqdm(total=len(resources)) as pBar: for res_id, data in resources: arc_mesh = ArcMesh() in_stream = ResStream(data) filepath = os.path.join( - MESH_DIRECTORY, + directory, f'{res_id:d}.json' ) arc_mesh.load_binary(in_stream) @@ -522,7 +527,7 @@ def pack_mesh(): resources.append([res_id, out_stream.get_bytes()]) - save_cache_file('Mesh.cache.new', resources) + save_cache_file('Mesh.cache', resources) def test_mesh(): @@ -545,16 +550,15 @@ def test_mesh(): def unpack_visual(): - init_visual() - resources = load_cache_file('Visual.cache') + directory = create_unpack_directory(VISUAL_DIRECTORY) with tqdm(total=len(resources)) as pBar: for res_id, data in resources: arc_visual = ArcVisual() in_stream = ResStream(data) filepath = os.path.join( - VISUAL_DIRECTORY, + directory, f'{res_id:d}.json' ) arc_visual.load_binary(in_stream) @@ -581,7 +585,7 @@ def pack_visual(): resources.append([res_id, out_stream.get_bytes()]) - save_cache_file('Visual.cache.new', resources) + save_cache_file('Visual.cache', resources) def test_visual(): @@ -604,16 +608,15 @@ def test_visual(): def unpack_motion(): - init_motion() - resources = load_cache_file('Motion.cache') + directory = create_unpack_directory(MOTION_DIRECTORY) with tqdm(total=len(resources)) as pBar: for res_id, data in resources: arc_motion = ArcMotion() in_stream = ResStream(data) filepath = os.path.join( - MOTION_DIRECTORY, + directory, f'{res_id:d}.json' ) arc_motion.load_binary(in_stream) @@ -640,7 +643,7 @@ def pack_motion(): resources.append([res_id, out_stream.get_bytes()]) - save_cache_file('Motion.cache.new', resources) + save_cache_file('Motion.cache', resources) def test_motion(): @@ -663,16 +666,15 @@ def test_motion(): def unpack_tile(): - init_tile() - resources = load_cache_file('Tile.cache') + directory = create_unpack_directory(TILE_DIRECTORY) with tqdm(total=len(resources)) as pBar: for res_id, data in resources: arc_tile = ArcTileManager() in_stream = ResStream(data) filepath = os.path.join( - TILE_DIRECTORY, + directory, f'{res_id:d}.json' ) arc_tile.load_binary(in_stream) @@ -699,7 +701,7 @@ def pack_tile(): resources.append([res_id, out_stream.get_bytes()]) - save_cache_file('Tile.cache.new', resources) + save_cache_file('Tile.cache', resources) def test_tile(): @@ -722,16 +724,15 @@ def test_tile(): def unpack_skeleton(): - init_skeleton() - resources = load_cache_file('Skeleton.cache') + directory = create_unpack_directory(SKELETON_DIRECTORY) with tqdm(total=len(resources)) as pBar: for res_id, data in resources: arc_skeleton = ArcSkeleton() in_stream = ResStream(data) filepath = os.path.join( - SKELETON_DIRECTORY, + directory, f'{res_id:d}.json' ) arc_skeleton.load_binary(in_stream) @@ -759,7 +760,7 @@ def pack_skeleton(): resources.append([res_id, out_stream.get_bytes()]) - save_cache_file('Skeleton.cache.new', resources) + save_cache_file('Skeleton.cache', resources) def test_skeleton(): @@ -782,16 +783,15 @@ def test_skeleton(): def unpack_render(): - init_render() - resources = load_cache_file('render.cache') + directory = create_unpack_directory(RENDER_DIRECTORY) with tqdm(total=len(resources)) as pBar: for res_id, data in resources: arc_render = ArcRender() in_stream = ResStream(data) filepath = os.path.join( - RENDER_DIRECTORY, + directory, f'{res_id:d}.json' ) arc_render.load_binary(in_stream) @@ -819,7 +819,7 @@ def pack_render(): resources.append([res_id, out_stream.get_bytes()]) - save_cache_file('Render.cache.new', resources) + save_cache_file('Render.cache', resources) def test_render():