init
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user