97 lines
2.9 KiB
Python
97 lines
2.9 KiB
Python
import os
|
|
import json
|
|
import hashlib
|
|
import argparse
|
|
|
|
# ============================================================
|
|
# CONFIGURATION - edit these values for your game/project
|
|
# ============================================================
|
|
|
|
MANIFEST_FILENAME = "manifest.json"
|
|
|
|
# Files the updater must never touch (launcher itself, local settings, etc.)
|
|
IGNORE_FILES = {
|
|
MANIFEST_FILENAME,
|
|
"updater.exe", # Your compiled updater executable
|
|
"Option.ini", # Example: graphics/sound settings
|
|
"WindowsInfo.ini", # Example: window layout settings
|
|
}
|
|
|
|
# Folders the updater must never scan or update
|
|
IGNORE_FOLDERS = {
|
|
"screenshots",
|
|
"logs",
|
|
"replays",
|
|
}
|
|
|
|
# File extensions to always skip (lowercase, without the dot doesn't matter, include the dot)
|
|
IGNORE_EXTENSIONS = {
|
|
".log",
|
|
}
|
|
|
|
# ============================================================
|
|
# END CONFIGURATION
|
|
# ============================================================
|
|
|
|
|
|
def get_md5(filepath):
|
|
"""Computes the MD5 hash of a file."""
|
|
hash_md5 = hashlib.md5()
|
|
try:
|
|
with open(filepath, "rb") as f:
|
|
for chunk in iter(lambda: f.read(4096), b""):
|
|
hash_md5.update(chunk)
|
|
return hash_md5.hexdigest()
|
|
except IOError:
|
|
return None
|
|
|
|
|
|
def generate(client_dir):
|
|
if not os.path.exists(client_dir) or not os.path.isdir(client_dir):
|
|
print(f"Error: directory '{client_dir}' not found!")
|
|
return
|
|
|
|
manifest = {}
|
|
manifest_path = os.path.join(client_dir, MANIFEST_FILENAME)
|
|
|
|
print(f"Scanning client folder: {client_dir}")
|
|
|
|
for root, dirs, files in os.walk(client_dir):
|
|
# Filter out ignored folders (case-insensitive)
|
|
dirs[:] = [d for d in dirs if d.lower() not in IGNORE_FOLDERS]
|
|
|
|
for file in files:
|
|
if file in IGNORE_FILES:
|
|
continue
|
|
if any(file.lower().endswith(ext) for ext in IGNORE_EXTENSIONS):
|
|
continue
|
|
|
|
filepath = os.path.join(root, file)
|
|
|
|
# Path relative to the client folder (this is what the updater expects)
|
|
rel_path = os.path.relpath(filepath, client_dir)
|
|
|
|
# Convert Windows-style separators to web-style
|
|
rel_path_web = rel_path.replace("\\", "/")
|
|
|
|
file_hash = get_md5(filepath)
|
|
if file_hash:
|
|
manifest[rel_path_web] = file_hash
|
|
|
|
try:
|
|
with open(manifest_path, "w", encoding="utf-8") as f:
|
|
json.dump(manifest, f, indent=4)
|
|
print(f"Done! Manifest saved to: {manifest_path}")
|
|
print(f"Total files in manifest: {len(manifest)}")
|
|
except IOError as e:
|
|
print(f"Error saving manifest: {e}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description="Universal manifest generator for game updaters.")
|
|
parser.add_argument("client_path", help="Path to the client files folder")
|
|
|
|
args = parser.parse_args()
|
|
|
|
generate(args.client_path)
|