arkparse 0.5.1__tar.gz → 0.5.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. {arkparse-0.5.1 → arkparse-0.5.3}/.gitignore +3 -2
  2. {arkparse-0.5.1 → arkparse-0.5.3}/PKG-INFO +1 -1
  3. {arkparse-0.5.1 → arkparse-0.5.3}/pyproject.toml +1 -1
  4. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/api/json_api.py +6 -1
  5. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/logging/ark_save_logger.py +77 -0
  6. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/ark_game_object.py +24 -4
  7. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/ark_archive.py +6 -0
  8. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/ark_property.py +94 -32
  9. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_custom_item_data.py +24 -5
  10. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/saves/save_connection.py +15 -5
  11. {arkparse-0.5.1 → arkparse-0.5.3}/LICENSE +0 -0
  12. {arkparse-0.5.1 → arkparse-0.5.3}/README.md +0 -0
  13. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/__init__.py +0 -0
  14. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/api/__init__.py +0 -0
  15. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/api/base_api.py +0 -0
  16. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/api/dino_api.py +0 -0
  17. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/api/equipment_api.py +0 -0
  18. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/api/general_api.py +0 -0
  19. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/api/player_api.py +0 -0
  20. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/api/rcon_api.py +0 -0
  21. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/api/stackable_api.py +0 -0
  22. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/api/structure_api.py +0 -0
  23. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/ark_tribe.py +0 -0
  24. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/ABERRATION.PNG +0 -0
  25. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/LOST_COLONY.PNG +0 -0
  26. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/RAGNAROK.PNG +0 -0
  27. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/THE_ISLAND.PNG +0 -0
  28. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/__init__.py +0 -0
  29. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/heavy_inventory +0 -0
  30. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/tamable_dinos.txt +0 -0
  31. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/armor +0 -0
  32. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/armor_bp +0 -0
  33. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/armor_bp_n.json +0 -0
  34. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/armor_n.json +0 -0
  35. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/saddle +0 -0
  36. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/saddle_bp +0 -0
  37. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/saddle_bp_n.json +0 -0
  38. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/saddle_n.json +0 -0
  39. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/shield +0 -0
  40. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/shield_bp +0 -0
  41. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/shield_bp_n.json +0 -0
  42. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/shield_n.json +0 -0
  43. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/weapon +0 -0
  44. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/weapon_bp +0 -0
  45. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/weapon_bp_n.json +0 -0
  46. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/equipment/weapon_n.json +0 -0
  47. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/inventory/with_item_n.json +0 -0
  48. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/stackable/stackable +0 -0
  49. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/stackable/stackable_n.json +0 -0
  50. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/trait/trait +0 -0
  51. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/assets/templates/trait/trait_n.json +0 -0
  52. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/classes/__init__.py +0 -0
  53. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/classes/consumables.py +0 -0
  54. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/classes/dinos.py +0 -0
  55. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/classes/equipment.py +0 -0
  56. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/classes/placed_structures.py +0 -0
  57. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/classes/player.py +0 -0
  58. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/classes/resources.py +0 -0
  59. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/classes/traits.py +0 -0
  60. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/enums/__init__.py +0 -0
  61. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/enums/ark_dino_trait.py +0 -0
  62. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/enums/ark_enum.py +0 -0
  63. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/enums/ark_equipment_stat.py +0 -0
  64. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/enums/ark_item_quality.py +0 -0
  65. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/enums/ark_map.py +0 -0
  66. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/enums/ark_stat.py +0 -0
  67. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/ftp/__init__.py +0 -0
  68. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/ftp/ark_ftp_client.py +0 -0
  69. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/helpers/dino/is_wild_tamed.py +0 -0
  70. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/logging/__init__.py +0 -0
  71. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/bases/base.py +0 -0
  72. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/cluster_data/ark_cluster_data.py +0 -0
  73. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/cluster_data/cluster_data_dino.py +0 -0
  74. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/cluster_data/cluster_data_item.py +0 -0
  75. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/cryopods/cryopod.py +0 -0
  76. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/dinos/__init__.py +0 -0
  77. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/dinos/baby.py +0 -0
  78. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/dinos/dino.py +0 -0
  79. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/dinos/dino_ai_controller.py +0 -0
  80. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/dinos/dino_id.py +0 -0
  81. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/dinos/pedigree.py +0 -0
  82. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/dinos/stats.py +0 -0
  83. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/dinos/tamed_baby.py +0 -0
  84. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/dinos/tamed_dino.py +0 -0
  85. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/equipment/__armor_defaults.py +0 -0
  86. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/equipment/__equipment.py +0 -0
  87. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/equipment/__equipment_with_armor.py +0 -0
  88. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/equipment/__equipment_with_durability.py +0 -0
  89. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/equipment/__init__.py +0 -0
  90. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/equipment/armor.py +0 -0
  91. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/equipment/saddle.py +0 -0
  92. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/equipment/shield.py +0 -0
  93. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/equipment/weapon.py +0 -0
  94. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/misc/__parsed_object_base.py +0 -0
  95. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/misc/dino_owner.py +0 -0
  96. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/misc/inventory.py +0 -0
  97. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/misc/inventory_item.py +0 -0
  98. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/misc/object_crafter.py +0 -0
  99. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/misc/object_owner.py +0 -0
  100. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/misc/trait.py +0 -0
  101. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/stackables/__init__.py +0 -0
  102. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/stackables/_stackable.py +0 -0
  103. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/stackables/ammo.py +0 -0
  104. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/stackables/resource.py +0 -0
  105. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/structures/__init__.py +0 -0
  106. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/structures/structure.py +0 -0
  107. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/object_model/structures/structure_with_inventory.py +0 -0
  108. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/__init__.py +0 -0
  109. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_base_value_parser.py +0 -0
  110. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_base_value_validator.py +0 -0
  111. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_binary_reader_base.py +0 -0
  112. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_byte_operator.py +0 -0
  113. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_fast_shim.py +0 -0
  114. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/__init__.py +0 -0
  115. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/_property_insertor.py +0 -0
  116. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/_property_parser.py +0 -0
  117. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/_property_replacer.py +0 -0
  118. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/ark_binary_parser.py +0 -0
  119. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/ark_property.py +0 -0
  120. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/struct/__init__.py +0 -0
  121. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_dino_ancestor_entry.py +0 -0
  122. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_item_net_id.py +0 -0
  123. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_my_persistent_buff_datas.py +0 -0
  124. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_object_property.py +0 -0
  125. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_struct_type.py +0 -0
  126. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_tracked_actor_id_category_pair_with_bool.py +0 -0
  127. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_unique_net_id_repl.py +0 -0
  128. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_vector.py +0 -0
  129. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_vector_bool_pair.py +0 -0
  130. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_property_insertor.py +0 -0
  131. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_property_parser.py +0 -0
  132. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/_property_replacer.py +0 -0
  133. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/ark_binary_parser.py +0 -0
  134. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/ark_object.py +0 -0
  135. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/ark_property_container.py +0 -0
  136. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/ark_set.py +0 -0
  137. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/ark_value_type.py +0 -0
  138. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/array_property.py +0 -0
  139. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/game_object_reader_configuration.py +0 -0
  140. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/__init__.py +0 -0
  141. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/actor_transform.py +0 -0
  142. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_color.py +0 -0
  143. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_crafting_resource_requirement.py +0 -0
  144. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_dino_ancestor_entry.py +0 -0
  145. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_dino_order_id.py +0 -0
  146. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_gacha_resource_struct.py +0 -0
  147. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_gene_trait_struct.py +0 -0
  148. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_gigantoraptor_bonded_struct.py +0 -0
  149. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_int_point.py +0 -0
  150. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_item_craft_queue_entry.py +0 -0
  151. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_item_net_id.py +0 -0
  152. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_key_value_pair.py +0 -0
  153. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_linear_color.py +0 -0
  154. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_milestone_tree_level_and_index.py +0 -0
  155. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_my_persistent_buff_datas.py +0 -0
  156. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_object_property.py +0 -0
  157. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_painting_key_value.py +0 -0
  158. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_patrol_group_saved_data.py +0 -0
  159. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_player_death_reason.py +0 -0
  160. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_primal_saddle_structure.py +0 -0
  161. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_quat.py +0 -0
  162. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_rotator.py +0 -0
  163. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_server_custom_folder.py +0 -0
  164. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_struct_type.py +0 -0
  165. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_tracked_actor_id_category_pair.py +0 -0
  166. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_tracked_actor_id_category_pair_with_bool.py +0 -0
  167. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_tribe_alliance.py +0 -0
  168. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_tribe_rank_group.py +0 -0
  169. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_unique_net_id_repl.py +0 -0
  170. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_vector.py +0 -0
  171. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/ark_vector_bool_pair.py +0 -0
  172. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/object_reference.py +0 -0
  173. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/parsing/struct/unknown_struct.py +0 -0
  174. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/player/ark_character_config.py +0 -0
  175. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/player/ark_character_stats.py +0 -0
  176. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/player/ark_persistent_buff_data.py +0 -0
  177. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/player/ark_player.py +0 -0
  178. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/player/ark_tribute_item.py +0 -0
  179. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/saves/__init__.py +0 -0
  180. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/saves/asa_save.py +0 -0
  181. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/saves/header_location.py +0 -0
  182. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/saves/save_context.py +0 -0
  183. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/utils/__init__.py +0 -0
  184. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/utils/heatmap_visualization.py +0 -0
  185. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/utils/import_file.py +0 -0
  186. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/utils/json_utils.py +0 -0
  187. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/utils/map_images.py +0 -0
  188. {arkparse-0.5.1 → arkparse-0.5.3}/src/arkparse/utils/tm_files.py +0 -0
@@ -188,5 +188,6 @@ temp
188
188
  .venv**
189
189
  arkparse-fast-core/**
190
190
  /arkparse-fast-core
191
-
192
- **.zip
191
+ .serena/
192
+ **.zip
193
+ .claude/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arkparse
3
- Version: 0.5.1
3
+ Version: 0.5.3
4
4
  Summary: A package to parse and modify ark save files
5
5
  Project-URL: Homepage, https://github.com/VincentHenauGithub/ark-save-parser
6
6
  Author-email: Vincent Henau <vincent.henau.github@gmail.com>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "arkparse"
7
- version = "0.5.1"
7
+ version = "0.5.3"
8
8
  dependencies = [
9
9
  "rcon>=2.4.9",
10
10
  "numpy>=2.3.2",
@@ -455,7 +455,12 @@ class JsonApi:
455
455
  try:
456
456
  obj_uuid = SaveConnection.byte_array_to_uuid(row[0])
457
457
  byte_buffer = ArkBinaryParser(row[1], self.save.save_context)
458
- class_name = byte_buffer.read_name()
458
+ # Use the string-name-aware reader: some objects store their
459
+ # class as an inline string instead of a name-table id, which
460
+ # a raw read_name() can't resolve (raises when generate_unknown
461
+ # is off). Those are never items, so they fall through the
462
+ # filter below.
463
+ class_name, *_ = ArkGameObject.read_name(obj_uuid, byte_buffer)
459
464
 
460
465
  if "/PrimalItemArmor_" not in class_name and \
461
466
  "/PrimalItem_" not in class_name and \
@@ -52,6 +52,16 @@ class ArkSaveLogger:
52
52
  # Use _get_struct_path() for thread-safe access
53
53
  current_struct_path = []
54
54
  _allow_invalid_objects = None
55
+ # Governs mod-namespace objects (not /Game/ or /Script/). Defaults to True
56
+ # (skip & continue) for backward compatibility; set to False to hard-fail.
57
+ _allow_invalid_mod_objects = None
58
+ # Optional callback invoked when an object fails to parse. Signature:
59
+ # (obj_uuid, class_name, byte_buffer, error) -> None
60
+ # Used by tooling (e.g. the testbench) to capture failing objects for debug.
61
+ _object_failure_handler = None
62
+ # Optional callback invoked on a (non-fatal) struct size mismatch. Signature:
63
+ # (struct_type, data_size, start_position, end_position, byte_buffer) -> None
64
+ _struct_mismatch_handler = None
55
65
  _worker_logging_enabled = None # Whether logging is enabled in worker threads
56
66
  _file = ""
57
67
  _byte_buffer = None
@@ -140,10 +150,13 @@ class ArkSaveLogger:
140
150
  }
141
151
  ArkSaveLogger._file_viewer_enabled = True
142
152
  ArkSaveLogger._worker_logging_enabled = False
153
+ ArkSaveLogger._allow_invalid_objects = True
154
+ ArkSaveLogger._allow_invalid_mod_objects = True
143
155
  config = {
144
156
  "levels": ArkSaveLogger._log_level_states,
145
157
  "fve": False,
146
158
  "allow_invalid": True,
159
+ "allow_invalid_mod": True,
147
160
  "worker_logging": False
148
161
  }
149
162
  write_config_file(ArkSaveLogger.__LOG_CONFIG_FILE_NAME, config)
@@ -151,6 +164,7 @@ class ArkSaveLogger:
151
164
  ArkSaveLogger._log_level_states = config["levels"]
152
165
  ArkSaveLogger._file_viewer_enabled = config["fve"]
153
166
  ArkSaveLogger._allow_invalid_objects = config["allow_invalid"]
167
+ ArkSaveLogger._allow_invalid_mod_objects = config.get("allow_invalid_mod", True)
154
168
  ArkSaveLogger._worker_logging_enabled = config.get("worker_logging", False)
155
169
  # Update cached parser_log state for fast checks
156
170
  ArkSaveLogger._parser_log_enabled = (
@@ -220,6 +234,69 @@ class ArkSaveLogger:
220
234
  global_config["allow_invalid"] = state
221
235
  write_config_file(ArkSaveLogger.__LOG_CONFIG_FILE_NAME, global_config)
222
236
 
237
+ @staticmethod
238
+ def allow_invalid_mod_objects(state: bool = True, set_globally: bool = False):
239
+ """Governs parsing failures for mod-namespace objects (anything whose
240
+ class is not under /Game/ or /Script/). When False, such failures are
241
+ reraised instead of skipped. Defaults to True (skip & continue)."""
242
+ if ArkSaveLogger._allow_invalid_mod_objects is None:
243
+ ArkSaveLogger.__init_config()
244
+
245
+ ArkSaveLogger._allow_invalid_mod_objects = state
246
+
247
+ if set_globally:
248
+ global_config = read_config_file(ArkSaveLogger.__LOG_CONFIG_FILE_NAME)
249
+ global_config["allow_invalid_mod"] = state
250
+ write_config_file(ArkSaveLogger.__LOG_CONFIG_FILE_NAME, global_config)
251
+
252
+ @staticmethod
253
+ def set_object_failure_handler(handler):
254
+ """Register a callback invoked whenever an object fails to parse.
255
+
256
+ The handler receives ``(obj_uuid, class_name, byte_buffer, error)``. Pass
257
+ ``None`` to clear it. Exceptions raised by the handler are swallowed so
258
+ debug tooling can never break parsing. Intended for capturing failing
259
+ objects (binary + structured dump) for offline debugging.
260
+ """
261
+ ArkSaveLogger._object_failure_handler = handler
262
+
263
+ @staticmethod
264
+ def _notify_object_failure(obj_uuid, class_name, byte_buffer, error, **kwargs):
265
+ """Forward a parse failure to the registered handler.
266
+
267
+ ``kwargs`` carries optional context (e.g. ``kind`` of "game"/"archive" and
268
+ a ``reload_hint`` dict) so the handler can capture and reload different
269
+ object types appropriately. Handlers should accept ``**kwargs``.
270
+ """
271
+ handler = ArkSaveLogger._object_failure_handler
272
+ if handler is None:
273
+ return
274
+ try:
275
+ handler(obj_uuid, class_name, byte_buffer, error, **kwargs)
276
+ except Exception as e: # never let debug tooling break parsing
277
+ ArkSaveLogger.warning_log(f"object_failure_handler raised: {e}")
278
+
279
+ @staticmethod
280
+ def set_struct_mismatch_handler(handler):
281
+ """Register a callback invoked on a non-fatal struct size mismatch (a
282
+ struct parsed as a property list that didn't consume exactly data_size).
283
+
284
+ The handler receives ``(struct_type, data_size, start_position,
285
+ end_position, byte_buffer)``. Pass ``None`` to clear it. Exceptions are
286
+ swallowed. Intended for debug tooling to record under-/over-read structs.
287
+ """
288
+ ArkSaveLogger._struct_mismatch_handler = handler
289
+
290
+ @staticmethod
291
+ def _notify_struct_mismatch(struct_type, data_size, start_position, end_position, byte_buffer):
292
+ handler = ArkSaveLogger._struct_mismatch_handler
293
+ if handler is None:
294
+ return
295
+ try:
296
+ handler(struct_type, data_size, start_position, end_position, byte_buffer)
297
+ except Exception as e: # never let debug tooling break parsing
298
+ ArkSaveLogger.warning_log(f"struct_mismatch_handler raised: {e}")
299
+
223
300
  @staticmethod
224
301
  def enable_worker_logging(state: bool = True, set_globally: bool = False):
225
302
  """Enable or disable logging in parallel worker threads.
@@ -45,6 +45,8 @@ class ArkGameObject(ArkPropertyContainer):
45
45
  self.uuid = uuid
46
46
  self.blueprint = blueprint
47
47
  string_name = False
48
+ string_names: List[str] = []
49
+ string_name_offsets: List[int] = []
48
50
  super().__init__()
49
51
  if binary_reader:
50
52
  ArkSaveLogger.set_file(binary_reader, "debug.bin")
@@ -55,7 +57,7 @@ class ArkGameObject(ArkPropertyContainer):
55
57
  self.uuid2: UUID = None
56
58
  binary_reader.set_position(0)
57
59
 
58
- self.blueprint, string_name = ArkGameObject.read_name(uuid, binary_reader)
60
+ self.blueprint, string_name, string_names, string_name_offsets = ArkGameObject.read_name(uuid, binary_reader)
59
61
  ArkSaveLogger.parser_log(f"Read Blueprint: {self.blueprint} (String name: {string_name})")
60
62
 
61
63
  sContext : SaveContext = binary_reader.save_context
@@ -69,6 +71,14 @@ class ArkGameObject(ArkPropertyContainer):
69
71
  binary_reader.validate_uint32(0)
70
72
  if string_name:
71
73
  binary_reader.read_uint16()
74
+ # Names embedded in a string-name header are stored as
75
+ # strings (never as name-table refs), mirroring what the
76
+ # regular names block below would produce.
77
+ self.names = string_names
78
+ self.name_metadata = [
79
+ _NameMetadata(name, offset, True)
80
+ for name, offset in zip(string_names, string_name_offsets)
81
+ ]
72
82
 
73
83
  try:
74
84
  if not (no_header or string_name):
@@ -250,6 +260,8 @@ class ArkGameObject(ArkPropertyContainer):
250
260
  def read_name(obj_uuid: UUID, reader: ArkBinaryParser) -> str:
251
261
  reader.set_position(0)
252
262
  string_name = False
263
+ extra_names: List[str] = []
264
+ extra_offsets: List[int] = []
253
265
 
254
266
  try:
255
267
  class_name = reader.read_name()
@@ -260,18 +272,26 @@ class ArkGameObject(ArkPropertyContainer):
260
272
  try:
261
273
  unknow_id = reader.read_uint32()
262
274
  reader.validate_uint64(0)
263
- reader.read_int()
275
+ name_count = reader.read_int()
264
276
  class_name = reader.read_string()
265
277
  # reader.validate_uint32(0)
266
278
  string_name = True
279
+ # The string-name header carries a name count: the first string is
280
+ # the class, any further strings are the object's names (e.g. the
281
+ # instance name of a DeathItemCache) that the name-table format
282
+ # would store separately. Consume them so the trailing padding
283
+ # lines up (otherwise validate_uint32(0) hits the next length).
284
+ for _ in range(max(0, name_count - 1)):
285
+ extra_offsets.append(reader.position + 4)
286
+ extra_names.append(reader.read_string())
267
287
  ArkSaveLogger.parser_log(f"Object {obj_uuid} has string class name {class_name} instead of name table reference")
268
288
  except Exception as e:
269
289
  ArkSaveLogger.error_log(f"Error reading class name for object {obj_uuid}: {e}")
270
290
  reader.structured_print(to_default_file=True)
271
291
  # input("Press Enter to continue...")
272
292
  class_name = "UnknownClass"
273
-
274
- return class_name, string_name
293
+
294
+ return class_name, string_name, extra_names, extra_offsets
275
295
 
276
296
  def get_short_name(self) -> str:
277
297
  to_strip_end = [
@@ -73,6 +73,12 @@ class ArkArchive:
73
73
  except Exception as e:
74
74
  ArkSaveLogger.error_log(f"Error reading properties for object \'{obj.class_name}\' at {self.data.get_position()}: {e}")
75
75
  self.data.structured_print()
76
+ # Notify any registered debug handler (e.g. the testbench dumper).
77
+ # Archives reload from their raw bytes via ArkArchive(data, from_store).
78
+ ArkSaveLogger._notify_object_failure(
79
+ None, obj.class_name, self.data, e,
80
+ kind="archive", reload_hint={"from_store": from_store},
81
+ )
76
82
  raise e
77
83
  ArkSaveLogger.exit_struct()
78
84
 
@@ -173,7 +173,7 @@ class ArkProperty:
173
173
  # Public API
174
174
  # ---------------------------------------------------------------------------------------------
175
175
  @staticmethod
176
- def read_property(byte_buffer: "ArkBinaryParser", in_array: bool = False) -> Optional["ArkProperty"]:
176
+ def read_property(byte_buffer: "ArkBinaryParser", in_array: bool = False, struct_end: int = -1) -> Optional["ArkProperty"]:
177
177
  name_position = byte_buffer.get_position()
178
178
  value_position = 0
179
179
  byte_buffer.save_context.generate_unknown = True
@@ -185,7 +185,12 @@ class ArkProperty:
185
185
  ArkSaveLogger.parser_log("Exiting struct (None marker) (pos = " + str(byte_buffer.get_position()) + " (hex: " + hex(byte_buffer.get_position()) + "))")
186
186
  ArkSaveLogger.exit_struct()
187
187
 
188
- if byte_buffer.size() - byte_buffer.position >= 4 and byte_buffer.peek_int() == 0:
188
+ # Only skip the 4 trailing zeros if we haven't already reached the
189
+ # declared struct boundary. When struct_end is known and we're right
190
+ # at it, those zeros belong to the outer stream, not this struct.
191
+ if (struct_end == -1 or byte_buffer.position < struct_end) \
192
+ and byte_buffer.size() - byte_buffer.position >= 4 \
193
+ and byte_buffer.peek_int() == 0:
189
194
  byte_buffer.skip_bytes(4)
190
195
  return None
191
196
 
@@ -291,6 +296,18 @@ class ArkProperty:
291
296
  if key_type == ArkValueType.Struct:
292
297
  value_type = bb.read_name()
293
298
  else:
299
+ if key_type == ArkValueType.Byte:
300
+ # Enum-keyed map (e.g. TMap<TEnumAsByte<EFoo>, ...>): the key's
301
+ # enum type is serialized as a descriptor block before the value
302
+ # type: [enum name][int][enum path][int]. Consume it so the value
303
+ # type is read from the correct offset.
304
+ enum_key_type = bb.read_name()
305
+ bb.read_int()
306
+ enum_key_path = bb.read_name()
307
+ bb.read_int()
308
+ ArkSaveLogger.parser_log(
309
+ f"Enum-keyed map: enum={enum_key_type} ({enum_key_path})"
310
+ )
294
311
  value_type = bb.read_value_type_by_name()
295
312
  struct_names = bb.read_int()
296
313
  if struct_names > 0:
@@ -342,7 +359,13 @@ class ArkProperty:
342
359
  @staticmethod
343
360
  def read_struct_map(key_type: ArkValueType, bb: "ArkBinaryParser", map_name: str) -> "ArkProperty":
344
361
  props: List[ArkProperty] = []
345
- key_name = ArkProperty.read_property_value(key_type, bb)
362
+ if key_type == ArkValueType.Byte:
363
+ # Enum-keyed map entry: the key is the enum value name (e.g.
364
+ # E_ActorType_AAT::NewEnumerator0), serialized as a name reference
365
+ # rather than a single byte.
366
+ key_name = bb.read_name()
367
+ else:
368
+ key_name = ArkProperty.read_property_value(key_type, bb)
346
369
  with log_block(f"Map({key_name}:{map_name})"):
347
370
  while bb.has_more():
348
371
  p = ArkProperty.read_property(bb)
@@ -374,6 +397,16 @@ class ArkProperty:
374
397
 
375
398
  return prop
376
399
 
400
+ @staticmethod
401
+ def _has_struct_reader(struct_type: str) -> bool:
402
+ """Whether this struct type has a dedicated (fixed-layout) reader.
403
+
404
+ Types without one are read generically as a property list; see
405
+ ``_read_struct_body`` and the guarded array backup in
406
+ ``read_array_property``.
407
+ """
408
+ return ArkStructType.from_type_name(struct_type) in _STRUCT_READERS
409
+
377
410
  @staticmethod
378
411
  def read_array_property(key: str, type_: str, position: int, bb: "ArkBinaryParser", data_size: int) -> Tuple["ArkProperty", int]:
379
412
  # V14 no position in array
@@ -405,31 +438,51 @@ class ArkProperty:
405
438
  bb.set_position(bb.position - 4)
406
439
 
407
440
  array_items = bb.read_uint32()
441
+ array_end = data_start_position + data_size
408
442
 
409
- # if array_content_type == "PrimalCharacterStatusValueModifier":
410
- # ArkSaveLogger.set_log_level(ArkSaveLogger.LogTypes.PARSER, True)
443
+ # Structs without a dedicated reader are read generically as a property
444
+ # list (see _read_struct_body). That backup is reliable for well-formed,
445
+ # None-terminated property-list structs but can't be guaranteed for an
446
+ # arbitrary packed layout, so guard it: if a generic element read raises,
447
+ # recover by skipping to the array's known end and record the type for
448
+ # follow-up rather than failing the whole object. A dedicated reader
449
+ # raising is a real bug, so let that propagate.
450
+ has_reader = ArkProperty._has_struct_reader(array_content_type)
411
451
 
412
452
  with log_block(f"Arr({array_content_type})"):
413
453
  ArkSaveLogger.parser_log(
414
454
  f"[STRUCT ARRAY: key='none'; nr_of_value={array_items}; type={array_content_type}; bin_length={data_size}]"
415
455
  )
416
- struct_array = [
417
- ArkProperty.read_struct_property(bb, data_size, array_content_type, True)[0]
418
- for _ in range(array_items)
419
- ]
456
+ struct_array = []
457
+ try:
458
+ for _ in range(array_items):
459
+ struct_array.append(
460
+ ArkProperty.read_struct_property(bb, data_size, array_content_type, True)[0]
461
+ )
462
+ except Exception as exc:
463
+ if has_reader:
464
+ raise
465
+ ArkSaveLogger.warning_log(
466
+ f"Generic read of struct array '{array_content_type}' failed after "
467
+ f"{len(struct_array)}/{array_items} element(s): {exc}; skipping to end of array"
468
+ )
469
+ ArkSaveLogger._notify_struct_mismatch(
470
+ array_content_type, data_size, data_start_position, bb.position, bb
471
+ )
472
+ bb.set_position(array_end)
420
473
 
421
474
  prop = ArkProperty(key, type_, position, 0, struct_array)
422
- if bb.position != data_start_position + data_size:
475
+ if bb.position != array_end:
476
+ # The read didn't consume exactly the declared size. Record the
477
+ # mismatch (the testbench captures these) and realign to the end.
423
478
  ArkSaveLogger.warning_log(
424
- f"Array read incorrectly, bytes left to read: {data_start_position + data_size - bb.position}, current position: {bb.position}"
479
+ f"Array of struct '{array_content_type}' read incorrectly, "
480
+ f"bytes off: {array_end - bb.position}; realigning to end of array"
425
481
  )
426
- ArkSaveLogger.warning_log(f"Skipping to the end of the struct, type: {array_content_type}")
427
- bb.set_position(data_start_position + data_size)
428
- bb.structured_print(to_default_file=True)
429
- ArkSaveLogger.open_hex_view(True)
430
-
431
- # if array_content_type == "PrimalCharacterStatusValueModifier":
432
- # ArkSaveLogger.set_log_level(ArkSaveLogger.LogTypes.PARSER, False)
482
+ ArkSaveLogger._notify_struct_mismatch(
483
+ array_content_type, data_size, data_start_position, bb.position, bb
484
+ )
485
+ bb.set_position(array_end)
433
486
 
434
487
  return prop, start_values_pos
435
488
 
@@ -511,7 +564,12 @@ class ArkProperty:
511
564
  ark_struct_type = ArkStructType.from_type_name(struct_type)
512
565
 
513
566
  if (ark_struct_type is not None) or in_array:
514
- if in_array and bb.peek_name() == "None":
567
+ # Known fixed-layout structs (LinearColor/Vector/Color/...) are packed
568
+ # primitives with no None terminator. In archive parsing there is no name
569
+ # table, so peek_name() falls back to read_string() and would mis-read their
570
+ # packed float bytes as a string length, overflowing the buffer. Skip the
571
+ # None probe for these and let the dedicated reader consume the exact bytes.
572
+ if in_array and ark_struct_type not in _STRUCT_READERS and bb.peek_name() == "None":
515
573
  ArkSaveLogger.parser_log("Exiting struct (None marker)")
516
574
  return bb.read_name()
517
575
  if data_size <= 4:
@@ -521,34 +579,38 @@ class ArkProperty:
521
579
  ArkSaveLogger.parser_log(f"Reading struct {struct_type} with data size {data_size}")
522
580
  return _STRUCT_READERS[ark_struct_type](bb, data_size)
523
581
  if in_array:
582
+ # No dedicated reader for this struct type. Fall through to the
583
+ # generic property-list read below — the designed backup for unknown
584
+ # structs in arrays. It reads cleanly for well-formed, None-terminated
585
+ # property-list structs, and read_array_property validates the array's
586
+ # total size and recovers from any type it can't fully consume, so
587
+ # this is not by itself an error. Record the type once (quietly) so it
588
+ # is discoverable without the noise of a per-type warning.
524
589
  if struct_type not in UNSUPPORTED_STRUCTS:
525
- ArkSaveLogger.warning_log(f"Unsupported struct type {struct_type} in array")
590
+ ArkSaveLogger.parser_log(
591
+ f"No dedicated reader for struct '{struct_type}' in array; "
592
+ f"reading generically as a property list"
593
+ )
526
594
  UNSUPPORTED_STRUCTS.append(struct_type)
527
-
528
- # uncomment the lines below if you want to make objects of unknown structs
529
- # ArkSaveLogger.parser_log(f"Reading struct {struct_type} as array")
530
- # bb.structured_print(to_default_file=True)
531
- # bb.store()
532
- # ArkSaveLogger.error_log(f"Unsupported struct type {struct_type} in array")
533
- # ArkSaveLogger.open_hex_view(True)
534
- # raise ValueError(f"Unsupported struct type {struct_type}")
535
595
 
536
596
  ArkSaveLogger.parser_log(f"Reading struct {struct_type} with data size {data_size} as property list at position {bb.get_position()}")
537
597
  # Fallback: struct as property list
538
598
  position = bb.get_position()
539
- props = ArkProperty.read_struct_properties(bb)
599
+ props = ArkProperty.read_struct_properties(bb, struct_end=position + data_size)
540
600
  if bb.get_position() != position + data_size and not in_array:
541
601
  ArkSaveLogger.warning_log(f"WARNING: Struct reading position mismatch for type {struct_type}")
542
602
  ArkSaveLogger.warning_log(
543
603
  f"StructType: {struct_type}, DataSize: {data_size}, Position: {position}, CurrentPosition: {bb.get_position()}"
544
604
  )
605
+ # Notify any registered debug handler (e.g. the testbench recorder).
606
+ ArkSaveLogger._notify_struct_mismatch(struct_type, data_size, position, bb.get_position(), bb)
545
607
  bb.set_position(position + data_size)
546
608
  return props
547
609
 
548
610
  @staticmethod
549
- def read_struct_properties(bb: "ArkBinaryParser") -> ArkPropertyContainer:
611
+ def read_struct_properties(bb: "ArkBinaryParser", struct_end: int = -1) -> ArkPropertyContainer:
550
612
  props: List[ArkProperty] = []
551
- struct_property = ArkProperty.read_property(bb)
613
+ struct_property = ArkProperty.read_property(bb, struct_end=struct_end)
552
614
  if struct_property is not None:
553
615
  ArkSaveLogger.parser_log(
554
616
  f"Struct properties: {struct_property.name} {struct_property.type} {struct_property.value}"
@@ -556,7 +618,7 @@ class ArkProperty:
556
618
  while struct_property:
557
619
  props.append(struct_property)
558
620
  if bb.has_more():
559
- struct_property = ArkProperty.read_property(bb)
621
+ struct_property = ArkProperty.read_property(bb, struct_end=struct_end)
560
622
  if struct_property is not None:
561
623
  ArkSaveLogger.parser_log(
562
624
  f"Struct properties: {struct_property.name} {struct_property.type} {struct_property.value}"
@@ -92,7 +92,19 @@ class ArkCustomItemData:
92
92
  # ark_binary_data.validate_uint32(0)
93
93
  # self.skins.append([bp, shorthand])
94
94
 
95
- ark_binary_data.validate_name("None")
95
+ ark_binary_data.validate_name("None")
96
+
97
+ # Some modded CustomItemData (e.g. the Cryopods mod) append extra empty
98
+ # trailing sections, each serialized as a [uint32 0][None] pair. Vanilla
99
+ # data has none of these, so this loop is a no-op there; the next array
100
+ # element starts with a real name ("CustomDataBytes") whose first 4 bytes
101
+ # are non-zero, which stops the loop.
102
+ while (ark_binary_data.size() - ark_binary_data.position) >= 12 \
103
+ and ark_binary_data.peek_int() == 0 \
104
+ and ark_binary_data.peek_name(4) == "None":
105
+ ark_binary_data.read_uint32() # 0
106
+ ark_binary_data.read_name() # None
107
+ ArkSaveLogger.parser_log("Consumed trailing [0][None] padding in CustomItemData")
96
108
 
97
109
  ArkSaveLogger.parser_log(f"CustomItemData of type {self.custom_data_name} read successfully, total size: {total_size} bytes")
98
110
  for string in self.strings:
@@ -335,10 +347,17 @@ class ArkCustomItemData:
335
347
  nr_of_items = ark_binary_data.read_uint32()
336
348
  soft_classes = []
337
349
 
338
- while ark_binary_data.peek_int() != 0:
339
- obj_name = ark_binary_data.read_name()
340
- soft_classes.append(obj_name)
341
- ark_binary_data.validate_uint32(0)
350
+ # Each soft-class entry is an FSoftObjectPath.
351
+ # - With name table (game saves): single FName (name_id + always_zero) + SubPathString.
352
+ # - Without name table (archives, UE 5.5): FTopLevelAssetPath — PackageName string
353
+ # + AssetName string — followed by SubPathString.
354
+ has_name_table = ark_binary_data.save_context.has_name_table()
355
+ for _ in range(nr_of_items):
356
+ pkg_name = ark_binary_data.read_name() # PackageName (or full path when name table)
357
+ if not has_name_table:
358
+ ark_binary_data.read_name() # AssetName (archives only)
359
+ ark_binary_data.read_string() # SubPathString (usually empty)
360
+ soft_classes.append(pkg_name)
342
361
 
343
362
  return soft_classes
344
363
 
@@ -182,7 +182,7 @@ class SaveConnection:
182
182
  obj_uuid = _fast_uuid_from_bytes(key_bytes)
183
183
  try:
184
184
  reader = ArkBinaryParser(value_bytes, self.save_context)
185
- class_name, _ = ArkGameObject.read_name(obj_uuid, reader)
185
+ class_name, *_ = ArkGameObject.read_name(obj_uuid, reader)
186
186
  self._class_cache[obj_uuid] = class_name
187
187
  except Exception:
188
188
  pass
@@ -192,7 +192,7 @@ class SaveConnection:
192
192
  return self._class_cache[obj_uuid]
193
193
  bin = self.get_game_obj_binary(obj_uuid)
194
194
  reader = ArkBinaryParser(bin, self.save_context)
195
- class_name, string_name = ArkGameObject.read_name(obj_uuid, reader)
195
+ class_name, *_ = ArkGameObject.read_name(obj_uuid, reader)
196
196
  self._class_cache[obj_uuid] = class_name
197
197
  return class_name
198
198
 
@@ -402,7 +402,10 @@ class SaveConnection:
402
402
  cursor = conn.execute(query)
403
403
  for row in cursor:
404
404
  byte_buffer = ArkBinaryParser(row[0], self.save_context)
405
- class_name = byte_buffer.read_name()
405
+ # String-name-aware read: some objects store their class as an
406
+ # inline string instead of a name-table id, which a raw
407
+ # read_name() can't resolve (raises when generate_unknown is off).
408
+ class_name, *_ = ArkGameObject.read_name(None, byte_buffer)
406
409
  if class_name not in classes:
407
410
  classes.append(class_name)
408
411
  return classes
@@ -452,7 +455,7 @@ class SaveConnection:
452
455
  bin = self.get_game_obj_binary(obj_uuid)
453
456
  reader = ArkBinaryParser(bin, self.save_context)
454
457
 
455
- class_name, string_name = ArkGameObject.read_name(obj_uuid, reader)
458
+ class_name, *_ = ArkGameObject.read_name(obj_uuid, reader)
456
459
 
457
460
  obj = SaveConnection.parse_as_predefined_object(obj_uuid, class_name, reader)
458
461
 
@@ -488,7 +491,7 @@ class SaveConnection:
488
491
  continue
489
492
 
490
493
  byte_buffer = ArkBinaryParser(binary_data, self.save_context)
491
- class_name, _ = ArkGameObject.read_name(obj_uuid, byte_buffer)
494
+ class_name, *_ = ArkGameObject.read_name(obj_uuid, byte_buffer)
492
495
 
493
496
  if reader_config.blueprint_name_filter and not reader_config.blueprint_name_filter(class_name):
494
497
  continue
@@ -609,10 +612,17 @@ class SaveConnection:
609
612
  ArkSaveLogger.warning_log(f"Error parsing object {obj_uuid} of type {class_name}, skipping...")
610
613
  else:
611
614
  byte_buffer.structured_print(to_default_file=True)
615
+ if ArkSaveLogger._allow_invalid_mod_objects is False:
616
+ byte_buffer.find_names(type=2)
617
+ ArkSaveLogger.error_log(f"Error parsing mod object {obj_uuid} of type {class_name}: {e}")
618
+ reraise = True
612
619
  ArkSaveLogger.warning_log(f"Error parsing non-standard object of type {class_name}")
613
620
 
614
621
  # input("Press Enter to continue...")
615
622
 
623
+ # Notify any registered debug handler (e.g. the testbench dumper).
624
+ ArkSaveLogger._notify_object_failure(obj_uuid, class_name, byte_buffer, e, kind="game")
625
+
616
626
  SaveConnection.failed_parses[class_name] = SaveConnection.failed_parses.get(class_name, 0) + 1
617
627
  ArkSaveLogger.warning_log(f"Failed parses for this class: {SaveConnection.failed_parses[class_name]}")
618
628
 
File without changes
File without changes