arkparse 0.4.4__tar.gz → 0.5.1__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 (190) hide show
  1. {arkparse-0.4.4 → arkparse-0.5.1}/.gitignore +5 -0
  2. {arkparse-0.4.4 → arkparse-0.5.1}/PKG-INFO +38 -5
  3. {arkparse-0.4.4 → arkparse-0.5.1}/README.md +35 -4
  4. {arkparse-0.4.4 → arkparse-0.5.1}/pyproject.toml +4 -1
  5. arkparse-0.5.1/src/arkparse/__init__.py +3 -0
  6. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/api/base_api.py +2 -2
  7. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/api/dino_api.py +159 -76
  8. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/api/equipment_api.py +7 -4
  9. arkparse-0.5.1/src/arkparse/api/general_api.py +106 -0
  10. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/api/stackable_api.py +2 -2
  11. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/api/structure_api.py +104 -33
  12. arkparse-0.5.1/src/arkparse/assets/templates/trait/trait +0 -0
  13. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/classes/dinos.py +9 -3
  14. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/classes/equipment.py +4 -2
  15. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/ftp/ark_ftp_client.py +57 -2
  16. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/logging/ark_save_logger.py +109 -28
  17. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/ark_game_object.py +13 -4
  18. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/bases/base.py +5 -1
  19. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/cryopods/cryopod.py +3 -0
  20. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/dinos/baby.py +9 -0
  21. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/dinos/dino.py +50 -2
  22. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/dinos/stats.py +14 -2
  23. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/dinos/tamed_dino.py +15 -3
  24. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/equipment/__armor_defaults.py +40 -0
  25. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/equipment/__equipment.py +11 -1
  26. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/equipment/__equipment_with_armor.py +4 -4
  27. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/equipment/__equipment_with_durability.py +1 -1
  28. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/equipment/weapon.py +1 -1
  29. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/misc/__parsed_object_base.py +11 -2
  30. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/misc/inventory.py +14 -10
  31. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/structures/structure.py +7 -1
  32. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/structures/structure_with_inventory.py +9 -1
  33. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_base_value_parser.py +60 -4
  34. arkparse-0.5.1/src/arkparse/parsing/_fast_shim.py +224 -0
  35. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/ark_binary_parser.py +2 -2
  36. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/ark_binary_parser.py +28 -4
  37. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/ark_property.py +3 -0
  38. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/ark_property_container.py +63 -7
  39. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/ark_value_type.py +5 -4
  40. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/actor_transform.py +25 -17
  41. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_custom_item_data.py +3 -4
  42. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/player/ark_player.py +2 -1
  43. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/saves/asa_save.py +23 -3
  44. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/saves/save_connection.py +164 -50
  45. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/saves/save_context.py +8 -1
  46. arkparse-0.4.4/src/arkparse/__init__.py +0 -3
  47. arkparse-0.4.4/src/arkparse/api/general_api.py +0 -56
  48. {arkparse-0.4.4 → arkparse-0.5.1}/LICENSE +0 -0
  49. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/api/__init__.py +0 -0
  50. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/api/json_api.py +0 -0
  51. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/api/player_api.py +0 -0
  52. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/api/rcon_api.py +0 -0
  53. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/ark_tribe.py +0 -0
  54. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/ABERRATION.PNG +0 -0
  55. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/LOST_COLONY.PNG +0 -0
  56. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/RAGNAROK.PNG +0 -0
  57. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/THE_ISLAND.PNG +0 -0
  58. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/__init__.py +0 -0
  59. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/heavy_inventory +0 -0
  60. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/tamable_dinos.txt +0 -0
  61. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/armor +0 -0
  62. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/armor_bp +0 -0
  63. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/armor_bp_n.json +0 -0
  64. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/armor_n.json +0 -0
  65. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/saddle +0 -0
  66. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/saddle_bp +0 -0
  67. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/saddle_bp_n.json +0 -0
  68. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/saddle_n.json +0 -0
  69. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/shield +0 -0
  70. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/shield_bp +0 -0
  71. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/shield_bp_n.json +0 -0
  72. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/shield_n.json +0 -0
  73. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/weapon +0 -0
  74. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/weapon_bp +0 -0
  75. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/weapon_bp_n.json +0 -0
  76. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/equipment/weapon_n.json +0 -0
  77. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/inventory/with_item_n.json +0 -0
  78. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/stackable/stackable +0 -0
  79. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/stackable/stackable_n.json +0 -0
  80. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/assets/templates/trait/trait_n.json +0 -0
  81. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/classes/__init__.py +0 -0
  82. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/classes/consumables.py +0 -0
  83. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/classes/placed_structures.py +0 -0
  84. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/classes/player.py +0 -0
  85. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/classes/resources.py +0 -0
  86. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/classes/traits.py +0 -0
  87. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/enums/__init__.py +0 -0
  88. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/enums/ark_dino_trait.py +0 -0
  89. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/enums/ark_enum.py +0 -0
  90. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/enums/ark_equipment_stat.py +0 -0
  91. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/enums/ark_item_quality.py +0 -0
  92. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/enums/ark_map.py +0 -0
  93. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/enums/ark_stat.py +0 -0
  94. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/ftp/__init__.py +0 -0
  95. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/helpers/dino/is_wild_tamed.py +0 -0
  96. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/logging/__init__.py +0 -0
  97. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/cluster_data/ark_cluster_data.py +0 -0
  98. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/cluster_data/cluster_data_dino.py +0 -0
  99. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/cluster_data/cluster_data_item.py +0 -0
  100. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/dinos/__init__.py +0 -0
  101. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/dinos/dino_ai_controller.py +0 -0
  102. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/dinos/dino_id.py +0 -0
  103. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/dinos/pedigree.py +0 -0
  104. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/dinos/tamed_baby.py +0 -0
  105. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/equipment/__init__.py +0 -0
  106. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/equipment/armor.py +0 -0
  107. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/equipment/saddle.py +0 -0
  108. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/equipment/shield.py +0 -0
  109. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/misc/dino_owner.py +0 -0
  110. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/misc/inventory_item.py +0 -0
  111. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/misc/object_crafter.py +0 -0
  112. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/misc/object_owner.py +0 -0
  113. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/misc/trait.py +0 -0
  114. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/stackables/__init__.py +0 -0
  115. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/stackables/_stackable.py +0 -0
  116. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/stackables/ammo.py +0 -0
  117. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/stackables/resource.py +0 -0
  118. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/object_model/structures/__init__.py +0 -0
  119. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/__init__.py +0 -0
  120. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_base_value_validator.py +0 -0
  121. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_binary_reader_base.py +0 -0
  122. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_byte_operator.py +0 -0
  123. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/__init__.py +0 -0
  124. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/_property_insertor.py +0 -0
  125. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/_property_parser.py +0 -0
  126. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/_property_replacer.py +0 -0
  127. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/ark_property.py +0 -0
  128. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/struct/__init__.py +0 -0
  129. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/struct/ark_dino_ancestor_entry.py +0 -0
  130. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/struct/ark_item_net_id.py +0 -0
  131. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/struct/ark_my_persistent_buff_datas.py +0 -0
  132. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/struct/ark_object_property.py +0 -0
  133. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/struct/ark_struct_type.py +0 -0
  134. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/struct/ark_tracked_actor_id_category_pair_with_bool.py +0 -0
  135. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/struct/ark_unique_net_id_repl.py +0 -0
  136. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/struct/ark_vector.py +0 -0
  137. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_legacy_parsing/struct/ark_vector_bool_pair.py +0 -0
  138. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_property_insertor.py +0 -0
  139. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_property_parser.py +0 -0
  140. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/_property_replacer.py +0 -0
  141. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/ark_archive.py +0 -0
  142. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/ark_object.py +0 -0
  143. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/ark_set.py +0 -0
  144. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/array_property.py +0 -0
  145. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/game_object_reader_configuration.py +0 -0
  146. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/__init__.py +0 -0
  147. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_color.py +0 -0
  148. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_crafting_resource_requirement.py +0 -0
  149. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_dino_ancestor_entry.py +0 -0
  150. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_dino_order_id.py +0 -0
  151. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_gacha_resource_struct.py +0 -0
  152. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_gene_trait_struct.py +0 -0
  153. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_gigantoraptor_bonded_struct.py +0 -0
  154. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_int_point.py +0 -0
  155. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_item_craft_queue_entry.py +0 -0
  156. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_item_net_id.py +0 -0
  157. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_key_value_pair.py +0 -0
  158. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_linear_color.py +0 -0
  159. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_milestone_tree_level_and_index.py +0 -0
  160. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_my_persistent_buff_datas.py +0 -0
  161. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_object_property.py +0 -0
  162. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_painting_key_value.py +0 -0
  163. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_patrol_group_saved_data.py +0 -0
  164. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_player_death_reason.py +0 -0
  165. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_primal_saddle_structure.py +0 -0
  166. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_quat.py +0 -0
  167. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_rotator.py +2 -2
  168. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_server_custom_folder.py +0 -0
  169. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_struct_type.py +0 -0
  170. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_tracked_actor_id_category_pair.py +0 -0
  171. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_tracked_actor_id_category_pair_with_bool.py +0 -0
  172. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_tribe_alliance.py +0 -0
  173. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_tribe_rank_group.py +0 -0
  174. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_unique_net_id_repl.py +0 -0
  175. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_vector.py +0 -0
  176. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/ark_vector_bool_pair.py +0 -0
  177. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/object_reference.py +0 -0
  178. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/parsing/struct/unknown_struct.py +0 -0
  179. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/player/ark_character_config.py +0 -0
  180. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/player/ark_character_stats.py +0 -0
  181. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/player/ark_persistent_buff_data.py +0 -0
  182. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/player/ark_tribute_item.py +0 -0
  183. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/saves/__init__.py +0 -0
  184. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/saves/header_location.py +0 -0
  185. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/utils/__init__.py +0 -0
  186. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/utils/heatmap_visualization.py +0 -0
  187. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/utils/import_file.py +0 -0
  188. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/utils/json_utils.py +0 -0
  189. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/utils/map_images.py +0 -0
  190. {arkparse-0.4.4 → arkparse-0.5.1}/src/arkparse/utils/tm_files.py +0 -0
@@ -185,3 +185,8 @@ temp
185
185
  **/exports/**
186
186
  **/**.ark.gz
187
187
  /src/.idea
188
+ .venv**
189
+ arkparse-fast-core/**
190
+ /arkparse-fast-core
191
+
192
+ **.zip
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arkparse
3
- Version: 0.4.4
3
+ Version: 0.5.1
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>
@@ -11,6 +11,8 @@ Requires-Dist: matplotlib>=3.10.3
11
11
  Requires-Dist: numpy>=2.3.2
12
12
  Requires-Dist: pandas>=2.3.1
13
13
  Requires-Dist: rcon>=2.4.9
14
+ Provides-Extra: fast
15
+ Requires-Dist: arkparse-fast-core; extra == 'fast'
14
16
  Description-Content-Type: text/markdown
15
17
 
16
18
  # ArkParse: A Python Library for Reading and Modifying ARK Save Files
@@ -33,7 +35,6 @@ I mainly use this package for server management tasks. Some highlights include:
33
35
  - Sending random stats of the server to the chat
34
36
  - Monitoring player activity like when people log off and on and such
35
37
  - Randomly spawning bases with random loot for my friends to raid; probably my favorite feature (and the most complicated)
36
- If you're curious or want to explore the features yourself, you can find the project here: [ark-server-manager](https://github.com/VincentHenauGithub/ark-server-manager).
37
38
 
38
39
  Hope you find it useful or inspiring or both! 😊
39
40
 
@@ -63,17 +64,49 @@ I just hope it's usefull for someone!
63
64
  ---
64
65
  ## Installation
65
66
 
67
+ ### Standard Installation
68
+
66
69
  Install via pip:
67
70
 
68
71
  ```bash
69
72
  pip install arkparse
70
73
  ```
71
74
 
72
- Or install locally on your PC so you can add modifications
73
- First clone the repo and then run the following in repo directory:
75
+ For faster parsing, install with the optional Rust accelerator (requires pre-built wheels to be available on PyPI):
76
+
77
+ Current available wheels: MacOS, Windows and Linux; Python 3.9, 3.10, 3.11, 3.12, 3.13, 3.14 (3.13t and 3.14t)
74
78
  ```bash
79
+ pip install arkparse[fast]
80
+ ```
81
+
82
+ ### Recommended python version: Free-Threaded Python (~40% speedup)
83
+
84
+ ArkParse supports Python 3.13+ free-threaded builds (no-GIL), which provides additional performance benefits through parallel workloads. In my benchmarks this provides over **40% increased performance**, so I would highly recommend it!
85
+
86
+ ArkParse automatically detects if you are using free-threaded Python and parallelizes intensive tasks accordingly — no code changes required on your end.
87
+
88
+ Since free-threaded python is experimental I would advise using a virtual environment.
89
+
90
+ ### Development Installation
91
+
92
+ For local development, clone and install in editable mode:
93
+
94
+ ```bash
95
+ git clone https://github.com/VincentHenauGithub/ark-save-parser.git
96
+ cd ark-save-parser
75
97
  pip install -e .
76
98
  ```
99
+
100
+ **Optional: Rust Accelerator (up to ~20% increased performance single threaded mode and ~5% in free threaded mode)**
101
+
102
+ The Rust accelerator is something I started and is still very much not finished, it currently provides some decent performance benefits but I would like to see this become a much larger benefit. I will update that package in the future.
103
+
104
+ Requires [Rust](https://rustup.rs/) and [maturin](https://www.maturin.rs/):
105
+ ```bash
106
+ git clone https://github.com/VincentHenauGithub/arkparse-fast-core.git
107
+ cd arkparse-fast-core && pip install maturin && maturin develop --release
108
+ ```
109
+
77
110
  ---
78
111
 
79
112
  ### 4. **Quickstart**
@@ -233,7 +266,7 @@ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file
233
266
  ## Feedback & Support
234
267
 
235
268
  - **Issues or Feature Requests**: Open an issue on the repo!
236
- - **Help**: If you need help for something specific, you can always messageme, I will try to help you out
269
+ - **Help**: If you need help for something specific, you can always message me, I will try to help you out
237
270
 
238
271
  ## Donation
239
272
 
@@ -18,7 +18,6 @@ I mainly use this package for server management tasks. Some highlights include:
18
18
  - Sending random stats of the server to the chat
19
19
  - Monitoring player activity like when people log off and on and such
20
20
  - Randomly spawning bases with random loot for my friends to raid; probably my favorite feature (and the most complicated)
21
- If you're curious or want to explore the features yourself, you can find the project here: [ark-server-manager](https://github.com/VincentHenauGithub/ark-server-manager).
22
21
 
23
22
  Hope you find it useful or inspiring or both! 😊
24
23
 
@@ -48,17 +47,49 @@ I just hope it's usefull for someone!
48
47
  ---
49
48
  ## Installation
50
49
 
50
+ ### Standard Installation
51
+
51
52
  Install via pip:
52
53
 
53
54
  ```bash
54
55
  pip install arkparse
55
56
  ```
56
57
 
57
- Or install locally on your PC so you can add modifications
58
- First clone the repo and then run the following in repo directory:
58
+ For faster parsing, install with the optional Rust accelerator (requires pre-built wheels to be available on PyPI):
59
+
60
+ Current available wheels: MacOS, Windows and Linux; Python 3.9, 3.10, 3.11, 3.12, 3.13, 3.14 (3.13t and 3.14t)
59
61
  ```bash
62
+ pip install arkparse[fast]
63
+ ```
64
+
65
+ ### Recommended python version: Free-Threaded Python (~40% speedup)
66
+
67
+ ArkParse supports Python 3.13+ free-threaded builds (no-GIL), which provides additional performance benefits through parallel workloads. In my benchmarks this provides over **40% increased performance**, so I would highly recommend it!
68
+
69
+ ArkParse automatically detects if you are using free-threaded Python and parallelizes intensive tasks accordingly — no code changes required on your end.
70
+
71
+ Since free-threaded python is experimental I would advise using a virtual environment.
72
+
73
+ ### Development Installation
74
+
75
+ For local development, clone and install in editable mode:
76
+
77
+ ```bash
78
+ git clone https://github.com/VincentHenauGithub/ark-save-parser.git
79
+ cd ark-save-parser
60
80
  pip install -e .
61
81
  ```
82
+
83
+ **Optional: Rust Accelerator (up to ~20% increased performance single threaded mode and ~5% in free threaded mode)**
84
+
85
+ The Rust accelerator is something I started and is still very much not finished, it currently provides some decent performance benefits but I would like to see this become a much larger benefit. I will update that package in the future.
86
+
87
+ Requires [Rust](https://rustup.rs/) and [maturin](https://www.maturin.rs/):
88
+ ```bash
89
+ git clone https://github.com/VincentHenauGithub/arkparse-fast-core.git
90
+ cd arkparse-fast-core && pip install maturin && maturin develop --release
91
+ ```
92
+
62
93
  ---
63
94
 
64
95
  ### 4. **Quickstart**
@@ -218,7 +249,7 @@ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file
218
249
  ## Feedback & Support
219
250
 
220
251
  - **Issues or Feature Requests**: Open an issue on the repo!
221
- - **Help**: If you need help for something specific, you can always messageme, I will try to help you out
252
+ - **Help**: If you need help for something specific, you can always message me, I will try to help you out
222
253
 
223
254
  ## Donation
224
255
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "arkparse"
7
- version = "0.4.4"
7
+ version = "0.5.1"
8
8
  dependencies = [
9
9
  "rcon>=2.4.9",
10
10
  "numpy>=2.3.2",
@@ -22,6 +22,9 @@ classifiers = [
22
22
  # Add additional classifiers as needed
23
23
  ]
24
24
 
25
+ [project.optional-dependencies]
26
+ fast = ["arkparse-fast-core"]
27
+
25
28
  [project.urls]
26
29
  Homepage = "https://github.com/VincentHenauGithub/ark-save-parser"
27
30
 
@@ -0,0 +1,3 @@
1
+ from .saves.asa_save import AsaSave
2
+ from .classes import Classes
3
+ from .parsing.struct.actor_transform import MapCoords, ActorTransform
@@ -18,9 +18,9 @@ from arkparse.utils import ImportFile
18
18
  from arkparse.logging import ArkSaveLogger
19
19
 
20
20
  class BaseApi(StructureApi):
21
- def __init__(self, save, map: ArkMap):
21
+ def __init__(self, save, map: ArkMap = None):
22
22
  super().__init__(save)
23
- self.map = map
23
+ self.map = map if map is not None else self.save.map
24
24
 
25
25
  def __get_closest_to(self, structures: Dict[UUID, Structure], coords: MapCoords):
26
26
  closest = None
@@ -1,7 +1,10 @@
1
- from typing import Dict, List, Optional
1
+ from typing import Dict, List, Optional, Tuple
2
2
  from uuid import UUID, uuid4
3
3
  from pathlib import Path
4
4
  import os
5
+ import sys
6
+ import threading
7
+ from concurrent.futures import ThreadPoolExecutor
5
8
 
6
9
  from arkparse.object_model.cryopods.cryopod import Cryopod
7
10
  from arkparse.object_model.dinos.dino import Dino, DinoStats, DinoId
@@ -23,13 +26,26 @@ from arkparse.classes.dinos import Dinos
23
26
  from arkparse.object_model.misc.inventory import Inventory
24
27
  from arkparse.object_model.misc.inventory_item import InventoryItem
25
28
  from arkparse.object_model.dinos.pedigree import Pedigree
29
+ from arkparse.logging.ark_save_logger import mark_as_worker_thread
30
+
31
+
32
+ def _is_parallel_enabled() -> bool:
33
+ """Check if parallel parsing should be enabled (GIL is disabled)."""
34
+ if hasattr(sys, '_is_gil_enabled'):
35
+ return not sys._is_gil_enabled()
36
+ return False
37
+
38
+
39
+ _PARALLEL_ENABLED = _is_parallel_enabled()
40
+
26
41
 
27
42
  class DinoApi:
28
43
  _DEFAULT_CONFIG = GameObjectReaderConfiguration(
29
44
  blueprint_name_filter=lambda name: \
30
45
  name is not None and \
31
- (("Dinos/" in name and "_Character_" in name) or \
32
- ("PrimalItem_WeaponEmptyCryopod" in name or "PrimalItem_SCSCryopod" in name)))
46
+ (((("/Creatures/" in name) or ("/Dinos/" in name) or ("/SDinoVariants/" in name)) and "_Character_" in name) or \
47
+ ("DinoCharacterStatusComponent" in name) or \
48
+ ("PrimalItem_WeaponEmptyCryopod" in name or "PrimalItem_SCSCryopod" in name or "ItemDinoball.ItemDinoball_C" in name)))
33
49
 
34
50
  def __init__(self, save: AsaSave):
35
51
  self.save = save
@@ -37,6 +53,13 @@ class DinoApi:
37
53
  self.parsed_dinos: Dict[UUID, Dino] = {}
38
54
  self.parsed_cryopods: Dict[UUID, Cryopod] = {}
39
55
 
56
+ @staticmethod
57
+ def _create_dino(uuid: UUID, save: AsaSave, is_tamed: bool, is_baby: bool, bypass_inventory: bool = True) -> Dino:
58
+ if is_tamed:
59
+ return TamedBaby(uuid, save=save) if is_baby else TamedDino(uuid, save=save, bypass_inventory=bypass_inventory)
60
+ else:
61
+ return Baby(uuid, save=save) if is_baby else Dino(uuid, save=save)
62
+
40
63
  @staticmethod
41
64
  def is_applicable_bp(blueprint: str) -> bool:
42
65
  return DinoApi._DEFAULT_CONFIG.blueprint_name_filter(blueprint)
@@ -66,99 +89,159 @@ class DinoApi:
66
89
 
67
90
  dino = None
68
91
  if "Dinos/" in object.blueprint and "_Character_" in object.blueprint:
69
- is_tamed = object.get_property_value("TamedTimeStamp") is not None
70
-
71
92
  if uuid in self.parsed_dinos:
72
93
  dino = self.parsed_dinos[uuid]
73
94
  else:
74
- if is_tamed:
75
- dino = TamedDino(uuid, self.save)
76
- else:
77
- dino = Dino(uuid, self.save)
95
+ is_tamed = object.get_property_value("TamedTimeStamp") is not None
96
+ is_baby = object.get_property_value("bIsBaby", False)
97
+ dino = DinoApi._create_dino(uuid, self.save, is_tamed, is_baby)
78
98
  self.parsed_dinos[uuid] = dino
79
99
 
80
100
  return dino
81
101
 
82
- def get_all(self, config = None, include_cryos: bool = True, include_wild: bool = True, include_tamed: bool = True, include_babies: bool = True, only_cryopodded: bool = False) -> Dict[UUID, Dino]:
102
+ def get_all(self, config = None, include_cryos: bool = True, include_wild: bool = True, include_tamed: bool = True, include_babies: bool = True, only_cryopodded: bool = False, max_workers: int = 6, bypass_inventory: bool = True) -> Dict[UUID, Dino]:
83
103
  ArkSaveLogger.api_log("Retrieving all dinos from save...")
84
104
 
85
105
  objects = self.get_all_objects(config)
106
+
86
107
  dinos = {}
87
108
 
88
109
  if self.all_objects and len(objects) != len(self.all_objects):
89
110
  ArkSaveLogger.api_log(f"Found {len(objects)} dinos, parsing them... (and retrieving inventories)")
90
111
 
112
+ # Classify objects into categories for parallel processing
113
+ dino_objects_to_parse: List[Tuple[UUID, ArkGameObject, bool, bool]] = [] # (uuid, obj, is_tamed, is_baby)
114
+ cryopod_objects_to_parse: List[Tuple[UUID, ArkGameObject]] = [] # (uuid, obj)
115
+
91
116
  for key, obj in objects.items():
92
- try:
93
- dino = None
94
- if not only_cryopodded and "Dinos/" in obj.blueprint and "_Character_" in obj.blueprint:
95
- is_tamed = obj.get_property_value("TamedTimeStamp") is not None
96
- is_baby = obj.get_property_value("bIsBaby", False)
97
-
98
- if obj.uuid in self.parsed_dinos:
99
- if is_tamed and include_tamed:
100
- if is_baby and include_babies:
101
- dino = self.parsed_dinos[obj.uuid]
102
- else:
103
- dino = self.parsed_dinos[obj.uuid]
104
- elif not is_tamed and include_wild:
105
- if is_baby and include_babies:
106
- dino = self.parsed_dinos[obj.uuid]
107
- else:
108
- dino = self.parsed_dinos[obj.uuid]
109
- elif is_tamed and include_tamed:
110
- if is_baby and include_babies:
111
- dino = TamedBaby(obj.uuid, save=self.save)
112
- else:
113
- dino = TamedDino(obj.uuid, save=self.save)
114
- self.parsed_dinos[obj.uuid] = dino
115
- elif include_wild and not is_tamed:
116
- if is_baby and include_babies:
117
- dino = Baby(obj.uuid, save=self.save)
118
- else:
119
- dino = Dino(obj.uuid, save=self.save)
120
- self.parsed_dinos[obj.uuid] = dino
121
-
122
- elif ("PrimalItem_SCSCryopod" in obj.blueprint or "PrimalItem_WeaponEmptyCryopod" in obj.blueprint) and include_cryos and include_tamed:
123
- if not obj.get_property_value("bIsEngram", default=False) and obj.get_property_value("CustomItemDatas") is not None:
124
- if obj.uuid in self.parsed_cryopods:
125
- is_baby = self.parsed_cryopods[obj.uuid].dino is not None and isinstance(self.parsed_cryopods[obj.uuid].dino, TamedBaby)
126
- if is_baby and include_babies:
127
- dino = self.parsed_cryopods[obj.uuid].dino
128
- else:
129
- dino = self.parsed_cryopods[obj.uuid].dino
130
- if dino is not None:
131
- self.parsed_dinos[dino.uuid] = dino
132
- else:
133
- try:
134
- cryopod = Cryopod(obj.uuid, save=self.save)
135
- self.parsed_cryopods[obj.uuid] = cryopod
136
- if cryopod.dino is not None:
137
- dino = cryopod.dino
138
- dino.is_cryopodded = True
139
- except Exception as e:
140
- if "Unsupported embedded data version" in str(e):
141
- ArkSaveLogger.warning_log(f"Skipping cryopod {obj.uuid} due to unsupported embedded data version (pre Unreal 5.5)")
142
- continue
143
- ArkSaveLogger.set_log_level(ArkSaveLogger.LogTypes.PARSER, True)
144
- cryopod = Cryopod(obj.uuid, save=self.save)
145
- ArkSaveLogger.set_log_level(ArkSaveLogger.LogTypes.PARSER, False)
146
- ArkSaveLogger.error_log(f"Error parsing cryopod {obj.uuid}: {e}")
147
- raise e
148
- finally:
149
- ArkSaveLogger.set_log_level(ArkSaveLogger.LogTypes.PARSER, False)
150
- if dino is not None:
151
- dinos[key] = dino
152
- except Exception as e:
153
- if ArkSaveLogger._allow_invalid_objects:
154
- ArkSaveLogger.error_log(f"Failed to parse dino {obj.uuid}: {e}")
155
- else:
156
- raise e
117
+ if not only_cryopodded and "Dinos/" in obj.blueprint and "_Character_" in obj.blueprint:
118
+ is_tamed = obj.get_property_value("TamedTimeStamp") is not None
119
+ is_baby = obj.get_property_value("bIsBaby", False)
120
+
121
+ if obj.uuid in self.parsed_dinos:
122
+ if (is_tamed and include_tamed) or (not is_tamed and include_wild):
123
+ dinos[key] = self.parsed_dinos[obj.uuid]
124
+ elif (is_tamed and include_tamed) or (not is_tamed and include_wild):
125
+ if not is_baby or include_babies:
126
+ dino_objects_to_parse.append((key, obj, is_tamed, is_baby))
127
+
128
+ elif ("PrimalItem_SCSCryopod" in obj.blueprint or "PrimalItem_WeaponEmptyCryopod" in obj.blueprint or "ItemDinoball.ItemDinoball_C" in obj.blueprint) and include_cryos and include_tamed:
129
+ if not obj.get_property_value("bIsEngram", default=False) and obj.get_property_value("CustomItemDatas") is not None:
130
+ if obj.uuid in self.parsed_cryopods:
131
+ self._collect_cached_cryopod(self.parsed_cryopods[obj.uuid], key, dinos, include_babies)
132
+ else:
133
+ cryopod_objects_to_parse.append((key, obj))
134
+
135
+ # Parse dinos - parallel when GIL is disabled
136
+ if dino_objects_to_parse:
137
+ self._parse_dinos_batch(dino_objects_to_parse, dinos, max_workers, bypass_inventory)
138
+
139
+ # Parse cryopods - parallel when GIL is disabled
140
+ if cryopod_objects_to_parse:
141
+ self._parse_cryopods_batch(cryopod_objects_to_parse, dinos, include_babies, max_workers)
157
142
 
158
143
  ArkSaveLogger.api_log(f"Parsed {len(dinos)} dinos")
159
144
 
160
145
  return dinos
161
-
146
+
147
+ def _collect_cached_cryopod(self, cryopod: Cryopod, key: UUID, dinos: Dict[UUID, Dino], include_babies: bool):
148
+ if cryopod.dino is not None:
149
+ is_baby = isinstance(cryopod.dino, TamedBaby)
150
+ if include_babies or not is_baby:
151
+ dinos[key] = cryopod.dino
152
+ self.parsed_dinos[cryopod.dino.uuid] = cryopod.dino
153
+
154
+ def _collect_parsed_cryopod(self, cryopod: Cryopod, key: UUID, dinos: Dict[UUID, Dino], include_babies: bool):
155
+ self.parsed_cryopods[cryopod.uuid] = cryopod
156
+ if cryopod.dino is not None:
157
+ cryopod.dino.is_cryopodded = True
158
+ is_baby = isinstance(cryopod.dino, TamedBaby)
159
+ if include_babies or not is_baby:
160
+ dinos[key] = cryopod.dino
161
+ self.parsed_dinos[cryopod.dino.uuid] = cryopod.dino
162
+
163
+ def _parse_dinos_batch(self, dino_objects_to_parse: List[Tuple[UUID, ArkGameObject, bool, bool]], dinos: Dict[UUID, Dino], max_workers: int, bypass_inventory: bool = True):
164
+ if _PARALLEL_ENABLED and max_workers > 1:
165
+ ArkSaveLogger.api_log(f"Parsing {len(dino_objects_to_parse)} dinos with {max_workers} workers...")
166
+ save = self.save
167
+ _worker_initialized = threading.local()
168
+ error_count = [0]
169
+
170
+ def parse_single_dino(item):
171
+ if not getattr(_worker_initialized, 'done', False):
172
+ mark_as_worker_thread()
173
+ _worker_initialized.done = True
174
+ key, obj, is_tamed, is_baby = item
175
+ try:
176
+ return (key, DinoApi._create_dino(obj.uuid, save, is_tamed, is_baby, bypass_inventory))
177
+ except Exception as e:
178
+ error_count[0] += 1
179
+ if error_count[0] <= 3:
180
+ ArkSaveLogger.error_log(f"Parallel dino parse error #{error_count[0]}: {type(e).__name__}: {e}")
181
+ return (key, None)
182
+
183
+ with ThreadPoolExecutor(max_workers=max_workers) as executor:
184
+ results = list(executor.map(parse_single_dino, dino_objects_to_parse))
185
+
186
+ for key, dino in results:
187
+ if dino is not None:
188
+ dinos[key] = dino
189
+ self.parsed_dinos[dino.uuid] = dino
190
+ else:
191
+ for key, obj, is_tamed, is_baby in dino_objects_to_parse:
192
+ try:
193
+ dino = DinoApi._create_dino(obj.uuid, self.save, is_tamed, is_baby, bypass_inventory)
194
+ dinos[key] = dino
195
+ self.parsed_dinos[dino.uuid] = dino
196
+ except Exception as e:
197
+ if ArkSaveLogger._allow_invalid_objects:
198
+ ArkSaveLogger.error_log(f"Failed to parse dino {obj.uuid}: {e}")
199
+ else:
200
+ raise e
201
+
202
+ def _parse_cryopods_batch(self, cryopod_objects_to_parse: List[Tuple[UUID, ArkGameObject]], dinos: Dict[UUID, Dino], include_babies: bool, max_workers: int):
203
+ if _PARALLEL_ENABLED and max_workers > 1:
204
+ ArkSaveLogger.api_log(f"Parsing {len(cryopod_objects_to_parse)} cryopods with {max_workers} workers...")
205
+ save = self.save
206
+ _worker_initialized = threading.local()
207
+
208
+ def parse_single_cryopod(item):
209
+ if not getattr(_worker_initialized, 'done', False):
210
+ mark_as_worker_thread()
211
+ _worker_initialized.done = True
212
+ key, obj = item
213
+ try:
214
+ return (key, Cryopod(obj.uuid, save=save), None)
215
+ except Exception as e:
216
+ if "Unsupported embedded data version" in str(e):
217
+ return (key, None, "unsupported_version")
218
+ return (key, None, str(e))
219
+
220
+ with ThreadPoolExecutor(max_workers=max_workers) as executor:
221
+ cryo_results = list(executor.map(parse_single_cryopod, cryopod_objects_to_parse))
222
+
223
+ for key, cryopod, error in cryo_results:
224
+ if cryopod is not None:
225
+ self._collect_parsed_cryopod(cryopod, key, dinos, include_babies)
226
+ elif error == "unsupported_version":
227
+ ArkSaveLogger.warning_log(f"Skipping cryopod due to unsupported embedded data version (pre Unreal 5.5)")
228
+ elif error is not None:
229
+ ArkSaveLogger.error_log(f"Error parsing cryopod: {error}")
230
+ if not ArkSaveLogger._allow_invalid_objects:
231
+ raise RuntimeError(f"Cryopod parse error: {error}")
232
+ else:
233
+ for key, obj in cryopod_objects_to_parse:
234
+ try:
235
+ cryopod = Cryopod(obj.uuid, save=self.save)
236
+ self._collect_parsed_cryopod(cryopod, key, dinos, include_babies)
237
+ except Exception as e:
238
+ if "Unsupported embedded data version" in str(e):
239
+ ArkSaveLogger.warning_log(f"Skipping cryopod {obj.uuid} due to unsupported embedded data version (pre Unreal 5.5)")
240
+ continue
241
+ ArkSaveLogger.error_log(f"Error parsing cryopod {obj.uuid}: {e}")
242
+ if not ArkSaveLogger._allow_invalid_objects:
243
+ raise e
244
+
162
245
  def get_at_location(self, map: ArkMap, coords: MapCoords, radius: float = 0.3, tamed: bool = True, untamed: bool = True) -> Dict[UUID, Dino]:
163
246
  dinos = self.get_all()
164
247
 
@@ -82,20 +82,23 @@ class EquipmentApi(GeneralApi):
82
82
  else:
83
83
  return None
84
84
 
85
- def get_all(self, cls: "EquipmentApi.Classes", config: GameObjectReaderConfiguration = None) -> Dict[UUID, Equipment]:
85
+ def get_all(self, cls: "EquipmentApi.Classes", config: GameObjectReaderConfiguration = None, max_workers: int = 6) -> Dict[UUID, Equipment]:
86
86
  def is_valid(obj: ArkGameObject):
87
87
  is_engram = obj.get_property_value("bIsEngram")
88
88
  return not is_engram
89
89
 
90
+ allowed = set(self.__get_cls_filter(cls))
90
91
  _config = GameObjectReaderConfiguration(
91
- blueprint_name_filter=lambda name: (True if config is None else config.blueprint_name_filter(name)) and name in self.__get_cls_filter(cls)
92
+ blueprint_name_filter=lambda name: (True if config is None else config.blueprint_name_filter(name)) and name in allowed
92
93
  )
93
94
 
94
- return super().get_all(cls, valid_filter=is_valid, config=_config)
95
+ return super().get_all(cls, valid_filter=is_valid, config=_config, max_workers=max_workers)
95
96
 
96
97
  def get_by_class(self, cls: "EquipmentApi.Classes", classes: List[str]) -> Dict[UUID, Equipment]:
98
+ allowed = set(self.__get_cls_filter(cls))
99
+ classes_set = set(classes)
97
100
  config = GameObjectReaderConfiguration(
98
- blueprint_name_filter=lambda name: name is not None and name in classes and name in self.__get_cls_filter(cls)
101
+ blueprint_name_filter=lambda name: name is not None and name in classes_set and name in allowed
99
102
  )
100
103
 
101
104
  return self.get_all(cls, config)
@@ -0,0 +1,106 @@
1
+ from typing import Dict, List, Tuple
2
+ from uuid import UUID
3
+ import sys
4
+ import threading
5
+ from concurrent.futures import ThreadPoolExecutor
6
+
7
+ from arkparse.logging.ark_save_logger import ArkSaveLogger, mark_as_worker_thread
8
+ from arkparse.object_model.ark_game_object import ArkGameObject
9
+ from arkparse.parsing import ArkBinaryParser
10
+ from arkparse.saves.asa_save import AsaSave
11
+ from arkparse.parsing import GameObjectReaderConfiguration
12
+ from arkparse.object_model.misc.__parsed_object_base import ParsedObjectBase
13
+
14
+
15
+ def _is_parallel_enabled() -> bool:
16
+ if hasattr(sys, '_is_gil_enabled'):
17
+ return not sys._is_gil_enabled()
18
+ return False
19
+
20
+
21
+ _PARALLEL_ENABLED = _is_parallel_enabled()
22
+
23
+
24
+ class GeneralApi:
25
+ def __init__(self, save: AsaSave, config: GameObjectReaderConfiguration= GameObjectReaderConfiguration()):
26
+ self.save = save
27
+ self.config = config
28
+ self.all_objects = None
29
+ self.parsed_objects: Dict[UUID, ParsedObjectBase] = {}
30
+
31
+ def get_all_objects(self, config: GameObjectReaderConfiguration = None) -> Dict[UUID, ArkGameObject]:
32
+ reuse = False
33
+ if config is None:
34
+ reuse = True
35
+ if self.all_objects is not None:
36
+ return self.all_objects
37
+
38
+ config = self.config
39
+
40
+ objects = self.save.get_game_objects(config)
41
+
42
+ if reuse:
43
+ self.all_objects = objects
44
+
45
+ return objects
46
+
47
+ def get_all(self, constructor, valid_filter = None, config = None, max_workers: int = 4) -> Dict[UUID, object]:
48
+ objects = self.get_all_objects(config)
49
+
50
+ parsed = {}
51
+ to_parse: List[Tuple[UUID, ArkGameObject]] = []
52
+
53
+ for key, obj in objects.items():
54
+ if valid_filter and not valid_filter(obj):
55
+ continue
56
+
57
+ if key in self.parsed_objects:
58
+ parsed[key] = self.parsed_objects[key]
59
+ else:
60
+ to_parse.append((key, obj))
61
+
62
+ self._parse_batch(to_parse, parsed, constructor, max_workers)
63
+
64
+ return parsed
65
+
66
+ def _parse_batch(self, to_parse: List[Tuple[UUID, ArkGameObject]], parsed: Dict, constructor, max_workers: int):
67
+ if _PARALLEL_ENABLED and max_workers > 1 and len(to_parse) > 0:
68
+ ArkSaveLogger.api_log(f"Parsing {len(to_parse)} objects with {max_workers} workers...")
69
+ save = self.save
70
+ _worker_initialized = threading.local()
71
+ error_count = [0]
72
+
73
+ def parse_single(item):
74
+ if not getattr(_worker_initialized, 'done', False):
75
+ mark_as_worker_thread()
76
+ _worker_initialized.done = True
77
+ key, obj = item
78
+ try:
79
+ return (key, constructor(obj.uuid, save), None)
80
+ except Exception as e:
81
+ error_count[0] += 1
82
+ if error_count[0] <= 3:
83
+ ArkSaveLogger.error_log(f"Parallel parse error #{error_count[0]}: {type(e).__name__}: {e}")
84
+ return (key, None, str(e))
85
+
86
+ with ThreadPoolExecutor(max_workers=max_workers) as executor:
87
+ results = list(executor.map(parse_single, to_parse))
88
+
89
+ for key, obj, error in results:
90
+ if obj is not None:
91
+ parsed[key] = obj
92
+ self.parsed_objects[key] = obj
93
+ elif error is not None:
94
+ if not ArkSaveLogger._allow_invalid_objects:
95
+ raise RuntimeError(f"Parse error for {key}: {error}")
96
+ else:
97
+ for key, obj in to_parse:
98
+ try:
99
+ parsed[key] = constructor(obj.uuid, self.save)
100
+ self.parsed_objects[key] = parsed[key]
101
+ except Exception as e:
102
+ if ArkSaveLogger._allow_invalid_objects:
103
+ ArkSaveLogger.error_log(f"Failed to parse object {obj.uuid}: {e}")
104
+ else:
105
+ raise e
106
+
@@ -25,13 +25,13 @@ class StackableApi(GeneralApi):
25
25
  config = StackableApi._DEFAULT_CONFIG
26
26
  super().__init__(save, config)
27
27
 
28
- def get_all(self, cls: "StackableApi.Classes", config = None) -> Dict[UUID, InventoryItem]:
28
+ def get_all(self, cls: "StackableApi.Classes", config = None, max_workers: int = 4) -> Dict[UUID, InventoryItem]:
29
29
  def is_valid(obj: ArkGameObject):
30
30
  is_bp = obj.get_property_value("bIsBlueprint")
31
31
  is_engram = obj.get_property_value("bIsEngram")
32
32
  return not (is_bp or is_engram)
33
33
 
34
- return super().get_all(cls, valid_filter=is_valid, config=config)
34
+ return super().get_all(cls, valid_filter=is_valid, config=config, max_workers=max_workers)
35
35
 
36
36
  def get_by_class(self, cls: "StackableApi.Classes", classes: List[str]) -> Dict[UUID, InventoryItem]:
37
37
  config = GameObjectReaderConfiguration(