上传文件至 /

This commit is contained in:
xingluo 2025-04-28 00:59:03 +08:00
commit dc907581b3

229
uuid.py Normal file
View File

@ -0,0 +1,229 @@
import os
import json
import re
import argparse
from uuid import UUID
def is_valid_uuid(uuid_str):
"""验证UUID格式有效性"""
try:
UUID(uuid_str)
return True
except ValueError:
return False
def get_uuid_variants(uuid_str):
"""生成UUID的两种形式带连字符和不带"""
if not is_valid_uuid(uuid_str):
return [uuid_str]
uuid_obj = UUID(uuid_str)
return [str(uuid_obj), uuid_obj.hex]
def replace_uuid_variants(content, old_variants, new_variants):
"""替换所有UUID变体"""
total = 0
for old, new in zip(old_variants, new_variants):
pattern = re.compile(r'\b' + re.escape(old) + r'\b')
content, count = pattern.subn(new, content)
total += count
return content, total
def process_snbt_file(file_path, old_uuid, new_uuid):
"""处理SNBT文件"""
old_forms = get_uuid_variants(old_uuid)
new_forms = get_uuid_variants(new_uuid)
try:
with open(file_path, 'r+', encoding='utf-8') as f:
content = f.read()
new_content, count = replace_uuid_variants(content, old_forms, new_forms)
if count > 0:
print(f"{os.path.basename(file_path)} 中替换了 {count} 处UUID")
f.seek(0)
f.write(new_content)
f.truncate()
else:
print(f"{os.path.basename(file_path)} 中未找到目标UUID")
except Exception as e:
print(f"处理 {file_path} 时出错: {str(e)}")
def replace_json_uuid(file_path, old_uuid, new_uuid):
"""处理JSON文件"""
try:
with open(file_path, 'r+', encoding='utf-8') as f:
data = json.load(f)
changes = 0
if isinstance(data, list):
for item in data:
if item.get('uuid') == old_uuid:
item['uuid'] = new_uuid
changes += 1
elif isinstance(data, dict):
if old_uuid in data:
data[new_uuid] = data.pop(old_uuid)
changes += 1
if changes > 0:
print(f"{os.path.basename(file_path)} 中替换了 {changes} 处UUID")
f.seek(0)
f.truncate()
json.dump(data, f, indent=4, ensure_ascii=False)
else:
print(f"{os.path.basename(file_path)} 中未找到目标UUID")
except Exception as e:
print(f"处理 {file_path} 时出错: {str(e)}")
def rename_uuid_files(root_dir, old_uuid, new_uuid):
"""重命名文件和目录"""
renamed_count = 0
for root, dirs, files in os.walk(root_dir, topdown=False):
# 先处理文件
for name in files:
if old_uuid in name:
new_name = name.replace(old_uuid, new_uuid)
src = os.path.join(root, name)
dst = os.path.join(root, new_name)
try:
os.rename(src, dst)
renamed_count += 1
print(f"已重命名文件:{name}{new_name}")
except Exception as e:
print(f"文件重命名失败 [{src}]: {str(e)}")
# 处理目录
for name in dirs:
if old_uuid in name:
new_name = name.replace(old_uuid, new_uuid)
src = os.path.join(root, name)
dst = os.path.join(root, new_name)
try:
os.rename(src, dst)
print(f"已重命名目录:{name}{new_name}")
except Exception as e:
print(f"目录重命名失败 [{src}]: {str(e)}")
print(f"完成重命名操作,共处理 {renamed_count} 个文件")
def process_directory(base_path, sub_path, old_uuid, new_uuid):
"""处理指定目录下的所有相关文件"""
target_dir = os.path.join(base_path, "world", sub_path)
if not os.path.exists(target_dir):
print(f"未找到目录:{target_dir}")
return
for root, _, files in os.walk(target_dir):
for file in files:
if file.endswith((".json", ".snbt")):
process_snbt_file(os.path.join(root, file), old_uuid, new_uuid)
def process_server(server_path, old_uuid, new_uuid):
"""主处理流程"""
# 处理核心JSON文件
for json_file in ["usercache.json", "usernamecache.json"]:
file_path = os.path.join(server_path, json_file)
if os.path.exists(file_path):
replace_json_uuid(file_path, old_uuid, new_uuid)
# 处理各模块数据
modules = [
("ftbteams/party", "FTB Teams队伍数据"),
("ftbteams/player", "FTB Teams玩家数据"),
("ftbchunks", "FTB Chunks数据"),
("ftbquests", "FTB Quests数据")
]
for path, name in modules:
print(f"\n正在处理{name}...")
process_directory(server_path, path, old_uuid, new_uuid)
# 处理world目录文件重命名
world_dir = os.path.join(server_path, "world")
if os.path.exists(world_dir):
print("\n正在处理文件重命名...")
rename_uuid_files(world_dir, old_uuid, new_uuid)
else:
print(f"未找到world目录{world_dir}")
def load_config(config_path):
"""加载配置文件"""
try:
with open(config_path, 'r', encoding='utf-8') as f:
config = json.load(f)
if not all(k in config for k in ("path", "mappings")):
raise ValueError("配置文件缺少必要字段")
if not isinstance(config["mappings"], dict):
raise TypeError("mappings字段必须为字典")
return config
except Exception as e:
print(f"配置文件错误: {str(e)}")
exit(1)
def main():
parser = argparse.ArgumentParser(description="Minecraft UUID迁移工具")
parser.add_argument("--config", help="配置文件路径")
args = parser.parse_args()
print("=" * 50)
print("Minecraft UUID迁移工具 v4.0")
print("=" * 50)
if args.config:
if not os.path.exists(args.config):
print(f"错误:配置文件 {args.config} 不存在")
exit(1)
config = load_config(args.config)
server_path = config["path"]
if not os.path.isdir(server_path):
print(f"错误:无效的服务端路径 {server_path}")
exit(1)
print(f"\n开始批量处理 {server_path}")
for old_uuid, new_uuid in config["mappings"].items():
print(f"\n{'='*30} 正在处理 {old_uuid[:8]}... {'='*30}")
process_server(server_path, old_uuid, new_uuid)
exit(0)
# 交互模式
while True:
server_path = input("\n请输入服务端路径输入q退出: ").strip()
if server_path.lower() == "q":
break
if not os.path.isdir(server_path):
print("错误:路径无效或不存在")
continue
while True:
print("\n" + "=" * 50)
old_uuid = input("请输入原UUID输入q返回上级: ").strip()
if old_uuid.lower() == "q":
break
if not is_valid_uuid(old_uuid):
print("错误无效的UUID格式")
continue
new_uuid = input("请输入新UUID: ").strip()
if not is_valid_uuid(new_uuid):
print("错误无效的新UUID格式")
continue
process_server(server_path, old_uuid, new_uuid)
choice = input("\n是否继续处理其他UUID(y/n): ").lower()
if choice != "y":
break
print("\n感谢使用!")
if __name__ == "__main__":
main()