Palworld存档逆向工程:从二进制数据到可编辑JSON的完整技术解析

发布时间:2026/9/9 21:40:58

Palworld存档逆向工程:从二进制数据到可编辑JSON的完整技术解析 Palworld存档逆向工程从二进制数据到可编辑JSON的完整技术解析【免费下载链接】palworld-save-toolsTools for converting Palworld .sav files to JSON and back项目地址: https://gitcode.com/gh_mirrors/pa/palworld-save-tools在《幻兽帕鲁》的游戏世界中每个玩家的进度都存储在神秘的.sav文件中。这些文件不仅是游戏状态的快照更是包含角色、帕鲁、建筑、物品等所有游戏元素的复杂数据结构。传统上这些二进制文件对于普通玩家来说是不可读的但通过palworld-save-tools项目我们可以将这些看似神秘的二进制数据转换为人类可读的JSON格式实现真正的存档深度编辑。问题场景为什么需要存档编辑工具当玩家面临以下技术挑战时存档编辑工具变得至关重要游戏平衡调整想要微调帕鲁属性或角色能力但游戏内选项有限存档修复需求游戏崩溃或数据损坏后需要手动修复存档文件数据迁移任务在不同服务器或玩家ID之间转移游戏进度自动化管理服务器管理员需要批量处理多个存档文件技术研究目的理解游戏内部数据结构和存储机制传统方法通常依赖于十六进制编辑器需要深入理解Unreal Engine的序列化格式。而palworld-save-tools提供了更优雅的解决方案。核心原理Palworld存档格式的技术解剖存档文件结构解析Palworld的.sav文件采用Unreal Engine的序列化格式包含多层压缩和编码。核心文件结构如下.sav文件结构 ├── 头部信息 (12-24字节) │ ├── 未压缩数据长度 (4字节) │ ├── 压缩数据长度 (4字节) │ ├── 魔数字节 PlZ (3字节) │ └── 保存类型 (1字节) ├── 压缩数据块 (Zlib压缩) │ └── GVAS格式数据 │ ├── 版本信息 │ ├── 时间戳 │ └── 游戏数据主体 └── 可选第二层压缩 (类型0x32)关键技术实现项目通过palworld_save_tools/palsav.py中的解压缩函数处理存档文件# 解压缩核心逻辑 def decompress_sav_to_gvas(data: bytes) - tuple[bytes, int]: uncompressed_len int.from_bytes(data[0:4], byteorderlittle) compressed_len int.from_bytes(data[4:8], byteorderlittle) magic_bytes data[8:11] if magic_bytes bCNK: # 处理特殊格式 # 调整偏移量处理额外头部 data_start_offset 24 else: data_start_offset 12 # 验证魔数字节 if magic_bytes ! MAGIC_BYTES: raise Exception(f无效的Palworld存档文件) # 处理不同的压缩类型 if save_type 0x31: # 单层Zlib压缩 uncompressed_data zlib.decompress(data[data_start_offset:]) elif save_type 0x32: # 双层Zlib压缩 uncompressed_data zlib.decompress(data[data_start_offset:]) uncompressed_data zlib.decompress(uncompressed_data)数据类型映射系统palworld_save_tools/paltypes.py定义了游戏数据结构到Python类型的完整映射PALWORLD_TYPE_HINTS { .worldSaveData.CharacterSaveParameterMap.Key: StructProperty, .worldSaveData.CharacterSaveParameterMap.Value: StructProperty, .worldSaveData.ItemContainerSaveData.Key: StructProperty, .worldSaveData.ItemContainerSaveData.Value: StructProperty, .worldSaveData.GroupSaveDataMap.Key: Guid, .worldSaveData.GroupSaveDataMap.Value: StructProperty, # ... 更多类型定义 }实践步骤构建完整的存档处理流程环境准备与项目部署Python环境要求Python 3.9或更高版本项目克隆从官方仓库获取最新代码git clone https://gitcode.com/gh_mirrors/pa/palworld-save-tools cd palworld-save-tools依赖检查项目设计为无额外依赖仅需标准库# 验证Python环境 python --version # 安装为可执行包 pip install -e .基本转换操作SAV到JSON转换# 基本转换 python convert.py Level.sav # 指定输出路径 python convert.py Level.sav --output custom_output.json # 压缩JSON输出处理大文件 python convert.py Level.sav --minify-json # 强制转换类型 python convert.py Level.sav --to-jsonJSON到SAV转换# 基本转换 python convert.py Level.sav.json # 强制转换类型 python convert.py Level.sav.json --from-json # 覆盖现有文件 python convert.py Level.sav.json --force高级数据处理技巧选择性数据解析对于大型存档文件可以只解析感兴趣的部分以提升性能# 只解析公会和角色数据 python convert.py Level.sav \ --custom-properties \ .worldSaveData.GroupSaveDataMap,\ .worldSaveData.CharacterSaveParameterMap.Value.RawData处理特殊数据类型游戏中的浮点数特殊值需要特殊处理# 将NaN/Inf转换为null python convert.py Level.sav --convert-nan-to-null技术架构深度解析模块化设计架构palworld-save-tools/ ├── palworld_save_tools/ │ ├── commands/ │ │ └── convert.py # 命令行接口 │ ├── rawdata/ # 原始数据解析器 │ │ ├── character.py # 角色数据 │ │ ├── base_camp.py # 基地数据 │ │ ├── item_container.py # 物品容器 │ │ └── ... # 其他数据模块 │ ├── archive.py # 存档读写器 │ ├── gvas.py # GVAS格式处理 │ ├── palsav.py # SAV压缩解压 │ └── paltypes.py # 类型映射定义 └── tests/ # 测试套件核心模块职责说明archive.py- 提供FArchiveReader和FArchiveWriter类处理Unreal Engine的二进制序列化格式gvas.py- 实现GVASGeneric Variant Asset Serialization格式的解析和生成palsav.py- 处理Palworld特有的压缩格式和文件结构rawdata/- 包含所有游戏数据结构的解析器每个文件对应一个特定的游戏数据类型数据流处理流程原始SAV文件 ↓ palsav.decompress_sav_to_gvas() # 解压缩 ↓ gvas.GvasFile.read() # 解析GVAS结构 ↓ paltypes类型映射 # 应用类型提示 ↓ rawdata模块解析 # 解析具体游戏数据 ↓ JSON序列化 # 输出可读格式进阶应用自定义数据处理与扩展开发集成到Python项目中作为Python包使用时可以直接导入核心功能from palworld_save_tools import GvasFile from palworld_save_tools.palsav import decompress_sav_to_gvas from palworld_save_tools.json_tools import CustomEncoder # 读取并解析存档 with open(Level.sav, rb) as f: data f.read() # 解压缩 uncompressed_data, _ decompress_sav_to_gvas(data) # 解析为GVAS对象 gvas_file GvasFile.read(uncompressed_data) # 转换为字典并自定义处理 save_data gvas_file.properties[SaveData] # 在这里进行自定义的数据处理逻辑创建自定义数据解析器当需要处理新的游戏数据结构时可以扩展rawdata模块# 在rawdata目录下创建新的解析器 from palworld_save_tools.archive import FArchiveReader, FArchiveWriter def decode_custom_data(reader: FArchiveReader, type_name: str, size: int, path: str): 自定义数据解码函数 # 读取数据并解析 result {} # ... 解析逻辑 return result def encode_custom_data(writer: FArchiveWriter, property_type: str, value: dict): 自定义数据编码函数 # 将字典编码回二进制 # ... 编码逻辑 return bytes_written # 在paltypes.py中注册新类型 PALWORLD_CUSTOM_PROPERTIES[.worldSaveData.CustomData] ( decode_custom_data, encode_custom_data )性能优化策略内存管理优化处理大型存档时需要注意内存使用# 流式处理大型JSON import ijson def process_large_save_in_chunks(json_file): 分块处理大型JSON文件 with open(json_file, rb) as f: # 使用ijson进行流式解析 parser ijson.parse(f) for prefix, event, value in parser: if prefix.endswith(.worldSaveData.CharacterSaveParameterMap): # 处理角色数据 process_character_data(value)并行处理加速from concurrent.futures import ThreadPoolExecutor import json def parallel_process_save_data(save_data): 并行处理存档的不同部分 with ThreadPoolExecutor(max_workers4) as executor: # 将数据分片处理 futures [] for chunk in chunk_data(save_data): future executor.submit(process_chunk, chunk) futures.append(future) # 收集结果 results [f.result() for f in futures] return merge_results(results)技术实现细节与注意事项数据完整性保证项目遵循转换正确性优先于性能的开发理念。SAV → JSON → SAV的完整转换流程应该产生位级相同的文件压缩前。这种设计确保了数据无损转换所有信息在转换过程中被完整保留逆向兼容性修改后的存档可以被游戏正常加载格式稳定性即使游戏更新已解析的数据结构仍可正确处理特殊数据类型处理GUID格式转换Unreal Engine使用特殊的GUID格式需要特殊处理# archive.py中的UUID处理 class UUID: def __init__(self, uuid_bytes: bytes): # Unreal Engine的字节序与标准UUID不同 self.bytes uuid_bytes classmethod def from_bytes(cls, data: bytes): # 重新排列字节序 return cls(bytes([ data[3], data[2], data[1], data[0], data[5], data[4], data[7], data[6], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15] ]))浮点数特殊值游戏中可能包含NaN、Infinity等特殊浮点数值需要在JSON转换时特殊处理# json_tools.py中的CustomEncoder class CustomEncoder(json.JSONEncoder): def encode(self, obj): # 处理特殊浮点数值 if isinstance(obj, float): if math.isnan(obj): return null elif math.isinf(obj): return null return super().encode(obj)错误处理与调试常见的错误场景文件格式错误非Palworld存档或损坏文件内存不足处理大型Level.sav文件时版本不兼容游戏更新导致数据结构变化编码问题Unicode字符处理异常调试工具使用# 启用详细日志 python convert.py Level.sav --debug # 只解析特定路径进行调试 python convert.py Level.sav \ --custom-properties .worldSaveData.CharacterSaveParameterMap应用场景示例实际案例解析案例1批量修改帕鲁属性import json from pathlib import Path def modify_pal_stats(save_file: Path, pal_id: str, new_stats: dict): 修改指定帕鲁的属性 # 加载存档 with open(save_file, r, encodingutf-8) as f: save_data json.load(f) # 查找并修改帕鲁数据 characters save_data[worldSaveData][CharacterSaveParameterMap] for char_id, char_data in characters.items(): if char_data.get(IsPlayer) False: # 帕鲁角色 if char_data.get(NickName) pal_id: # 修改属性 char_data[Talent_HP] new_stats.get(hp, char_data[Talent_HP]) char_data[Talent_Melee] new_stats.get(attack, char_data[Talent_Melee]) char_data[Talent_Shot] new_stats.get(ranged_attack, char_data[Talent_Shot]) char_data[Talent_Defense] new_stats.get(defense, char_data[Talent_Defense]) # 保存修改 with open(save_file, w, encodingutf-8) as f: json.dump(save_data, f, indent2)案例2服务器存档迁移工具def migrate_save_between_players(original_save: Path, new_player_id: str): 在不同玩家ID间迁移存档数据 # 解析存档 with open(original_save, rb) as f: data f.read() uncompressed_data, _ decompress_sav_to_gvas(data) gvas_file GvasFile.read(uncompressed_data) # 修改玩家ID相关数据 save_data gvas_file.properties[SaveData] # 更新公会中的玩家ID if GroupSaveDataMap in save_data: for group_id, group_data in save_data[GroupSaveDataMap].items(): if players in group_data: # 替换玩家ID group_data[players] [ new_player_id if player old_id else player for player in group_data[players] ] # 重新压缩并保存 new_data compress_gvas_to_sav(gvas_file.write()) new_save_path original_save.parent / fmigrated_{new_player_id}.sav with open(new_save_path, wb) as f: f.write(new_data)性能优化与最佳实践大型存档处理策略增量处理只解析需要修改的部分数据内存映射使用mmap处理超大文件缓存机制缓存已解析的数据结构并行解析对独立的数据块进行并行处理错误预防措施def safe_save_conversion(input_path: Path, output_path: Path): 安全的存档转换流程 # 1. 备份原始文件 backup_path input_path.with_suffix(.sav.backup) shutil.copy2(input_path, backup_path) try: # 2. 验证文件完整性 validate_save_file(input_path) # 3. 执行转换 result subprocess.run( [python, convert.py, str(input_path), --output, str(output_path)], capture_outputTrue, textTrue ) if result.returncode ! 0: raise Exception(f转换失败: {result.stderr}) # 4. 验证输出文件 validate_json_file(output_path) except Exception as e: # 5. 恢复备份 shutil.copy2(backup_path, input_path) raise e社区生态与扩展项目基于核心工具的衍生项目palworld-save-tools作为基础库催生了多个实用的扩展项目图形界面编辑器提供可视化的存档编辑界面服务器管理工具集成RCON和存档管理的完整解决方案存档修复工具专门处理损坏存档和版本迁移数据分析工具统计游戏数据和生成报告贡献指南与代码规范项目采用严格的代码质量要求无额外依赖核心功能仅使用Python标准库完整的测试覆盖所有功能都有对应的单元测试类型注解使用Python类型提示提高代码可读性文档完整性所有公共API都有完整的文档字符串下一步探索方向技术深度探索实时存档监控开发能够实时监控和修改游戏内存的工具版本兼容性自动化自动检测和处理不同游戏版本的数据结构差异云端存档管理构建基于Web的存档编辑和管理平台AI辅助编辑使用机器学习技术提供智能的存档修改建议社区协作机会插件系统开发设计可扩展的插件架构允许社区贡献新的数据解析器标准化数据格式定义跨工具的通用数据交换格式性能基准测试建立标准的性能测试套件优化处理速度多语言绑定为其他编程语言提供绑定接口学习资源指引对于希望深入了解游戏逆向工程和二进制数据处理的开发者建议学习Unreal Engine序列化理解GVAS和UE4的序列化机制掌握Python字节处理深入学习struct、zlib等标准库模块研究游戏数据格式分析其他游戏的存档格式比较异同参与开源项目通过贡献代码来积累实践经验通过palworld-save-tools项目开发者不仅能够深入理解《幻兽帕鲁》的游戏数据存储机制还能掌握通用的游戏逆向工程技术。这种技术能力可以应用于其他使用Unreal Engine的游戏为游戏数据分析和修改工具的开发提供坚实基础。项目源代码位于palworld_save_tools/目录核心转换逻辑在commands/convert.py中实现数据解析器分布在rawdata/目录下的各个模块中。测试用例位于tests/目录提供了完整的功能验证和示例。【免费下载链接】palworld-save-toolsTools for converting Palworld .sav files to JSON and back项目地址: https://gitcode.com/gh_mirrors/pa/palworld-save-tools创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/3 9:30:40

DDraceNetwork服务器搭建教程:轻松创建私人游戏房间

DDraceNetwork服务器搭建教程:轻松创建私人游戏房间 【免费下载链接】ddnet DDraceNetwork, a free cooperative platformer game 项目地址: https://gitcode.com/gh_mirrors/dd/ddnet DDraceNetwork是一款免费的合作平台游戏,基于Teeworlds修改而…

2026/9/8 15:39:36

atom-script错误排查指南:常见问题与解决方案汇总

atom-script错误排查指南:常见问题与解决方案汇总 【免费下载链接】atom-script :runner: Run ( scripts | selections | source ) in Atom 项目地址: https://gitcode.com/gh_mirrors/at/atom-script atom-script是Atom编辑器中一款强大的代码运行插件&…

2026/9/9 21:40:30

如何为 uBOLite 将过滤列表转换为声明式 ruleset?

如何为 uBOLite 将过滤列表转换为声明式 ruleset? 【免费下载链接】uBlock uBlock Origin - An efficient blocker for Chromium and Firefox. Fast and lean. 项目地址: https://gitcode.com/GitHub_Trending/ub/uBlock uBlock Origin 仓库中包含一个 MV3 分…

2026/9/9 21:40:29

弹幕互动直播从零搭建:链路拆解、脚本实战与避坑指南

简介:这套“抖音弹幕互动直播植物大战僵尸”资料,整合了实时互动直播所需的软件与全套教程,专为想在抖音、快手开启弹幕玩法的主播和内容运营者准备,重点解决直播间搭建、弹幕礼物联动、玩法配置等实际问题。内容覆盖游戏软件、开…

2026/9/9 21:40:29

XLA 如何调整性能 flags 提升 TPU 负载的执行性能?

XLA 如何调整性能 flags 提升 TPU 负载的执行性能? 【免费下载链接】tensorflow An Open Source Machine Learning Framework for Everyone 项目地址: https://gitcode.com/GitHub_Trending/te/tensorflow 如果你的 TensorFlow 程序跑在 TPU 上、已经走 XLA …

2026/9/9 21:40:29

Ultralytics utils源码精读:自动批处理、设备选择与工程化实践

干过几年CV训练、经常跟YOLO系列打交道的人,大概都有这种体验:模型结构看得懂、训练流程也跑得通,但一旦想动点"高级操作"——比如自动批量大小、自动切卡、状态恢复、超参搜索——就总感觉有一层窗户纸捅不破。这层纸,…

2026/9/9 21:35:29

文件类型检测只做 5 毫秒?Magika 实战速览

文件类型检测只做 5 毫秒?Magika 实战速览 【免费下载链接】magika Fast and accurate AI powered file content types detection 项目地址: https://gitcode.com/GitHub_Trending/ma/magika Magika 是一个用深度学习做文件内容类型检测的工具:给…

2026/9/9 13:11:35

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/8 7:15:15

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/9 16:31:09

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/9 0:00:48

MHS模型硬件标准:让大模型像调用软件一样控制物理设备

让Claude真正看着显微镜说“这个细胞形态不太对”,或者让大模型自己调一版机械臂的运动轨迹,这事儿听上去已经很接近科幻片了。但你真上手试一次就会发现,模型不缺智商,缺的是一个能插进显微镜、机械臂、激光控制器里的“通用插座…

2026/9/9 0:00:48

AI五大核心方向详解:从机器学习到大模型,零基础转行选哪条?

会有人告诉我,他想转行学AI,但打开招聘网站一看直接傻眼:机器学习、深度学习、自然语言处理、计算机视觉、大模型应用……满屏都是这些词,好像每个都会一点,又好像每个都离自己很远。还有人上来就问“学Python还是学Ja…

2026/9/9 0:00:49

从50行最小循环到生产级AI引擎:工程化改造全解析

直接说干货。这一章我写的不是那种"hello world跑通某个模型"的教程,而是把AI引擎当做一个真正要上线、要被人调用、要扛流量的系统来聊。从最初只有50行的最小循环,到能够承载生产流量的AI引擎,中间差的不是代码量,而是…

2026/9/7 16:23:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/7 22:46:00

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/9 10:21:54

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码