arkparse 0.5.0__tar.gz → 0.5.2__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 (189) hide show
  1. {arkparse-0.5.0 → arkparse-0.5.2}/.gitignore +3 -2
  2. {arkparse-0.5.0 → arkparse-0.5.2}/PKG-INFO +1 -1
  3. {arkparse-0.5.0 → arkparse-0.5.2}/pyproject.toml +1 -1
  4. arkparse-0.5.2/src/arkparse/__init__.py +3 -0
  5. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/api/base_api.py +2 -2
  6. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/api/dino_api.py +1 -1
  7. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/api/structure_api.py +28 -26
  8. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/classes/dinos.py +7 -2
  9. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/classes/equipment.py +4 -2
  10. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/ftp/ark_ftp_client.py +57 -2
  11. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/logging/ark_save_logger.py +77 -0
  12. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/ark_game_object.py +2 -0
  13. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/bases/base.py +5 -1
  14. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/dinos/dino.py +40 -2
  15. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/dinos/tamed_dino.py +12 -3
  16. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/misc/__parsed_object_base.py +4 -0
  17. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/structures/structure.py +7 -1
  18. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/structures/structure_with_inventory.py +9 -1
  19. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/ark_archive.py +6 -0
  20. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/ark_property.py +38 -8
  21. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/actor_transform.py +25 -17
  22. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_custom_item_data.py +23 -4
  23. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/saves/asa_save.py +12 -2
  24. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/saves/save_connection.py +9 -1
  25. arkparse-0.5.0/src/arkparse/__init__.py +0 -3
  26. {arkparse-0.5.0 → arkparse-0.5.2}/LICENSE +0 -0
  27. {arkparse-0.5.0 → arkparse-0.5.2}/README.md +0 -0
  28. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/api/__init__.py +0 -0
  29. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/api/equipment_api.py +0 -0
  30. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/api/general_api.py +0 -0
  31. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/api/json_api.py +0 -0
  32. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/api/player_api.py +0 -0
  33. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/api/rcon_api.py +0 -0
  34. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/api/stackable_api.py +0 -0
  35. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/ark_tribe.py +0 -0
  36. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/ABERRATION.PNG +0 -0
  37. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/LOST_COLONY.PNG +0 -0
  38. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/RAGNAROK.PNG +0 -0
  39. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/THE_ISLAND.PNG +0 -0
  40. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/__init__.py +0 -0
  41. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/heavy_inventory +0 -0
  42. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/tamable_dinos.txt +0 -0
  43. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/armor +0 -0
  44. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/armor_bp +0 -0
  45. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/armor_bp_n.json +0 -0
  46. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/armor_n.json +0 -0
  47. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/saddle +0 -0
  48. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/saddle_bp +0 -0
  49. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/saddle_bp_n.json +0 -0
  50. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/saddle_n.json +0 -0
  51. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/shield +0 -0
  52. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/shield_bp +0 -0
  53. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/shield_bp_n.json +0 -0
  54. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/shield_n.json +0 -0
  55. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/weapon +0 -0
  56. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/weapon_bp +0 -0
  57. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/weapon_bp_n.json +0 -0
  58. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/equipment/weapon_n.json +0 -0
  59. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/inventory/with_item_n.json +0 -0
  60. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/stackable/stackable +0 -0
  61. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/stackable/stackable_n.json +0 -0
  62. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/trait/trait +0 -0
  63. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/assets/templates/trait/trait_n.json +0 -0
  64. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/classes/__init__.py +0 -0
  65. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/classes/consumables.py +0 -0
  66. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/classes/placed_structures.py +0 -0
  67. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/classes/player.py +0 -0
  68. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/classes/resources.py +0 -0
  69. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/classes/traits.py +0 -0
  70. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/enums/__init__.py +0 -0
  71. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/enums/ark_dino_trait.py +0 -0
  72. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/enums/ark_enum.py +0 -0
  73. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/enums/ark_equipment_stat.py +0 -0
  74. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/enums/ark_item_quality.py +0 -0
  75. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/enums/ark_map.py +0 -0
  76. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/enums/ark_stat.py +0 -0
  77. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/ftp/__init__.py +0 -0
  78. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/helpers/dino/is_wild_tamed.py +0 -0
  79. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/logging/__init__.py +0 -0
  80. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/cluster_data/ark_cluster_data.py +0 -0
  81. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/cluster_data/cluster_data_dino.py +0 -0
  82. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/cluster_data/cluster_data_item.py +0 -0
  83. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/cryopods/cryopod.py +0 -0
  84. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/dinos/__init__.py +0 -0
  85. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/dinos/baby.py +0 -0
  86. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/dinos/dino_ai_controller.py +0 -0
  87. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/dinos/dino_id.py +0 -0
  88. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/dinos/pedigree.py +0 -0
  89. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/dinos/stats.py +0 -0
  90. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/dinos/tamed_baby.py +0 -0
  91. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/equipment/__armor_defaults.py +0 -0
  92. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/equipment/__equipment.py +0 -0
  93. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/equipment/__equipment_with_armor.py +0 -0
  94. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/equipment/__equipment_with_durability.py +0 -0
  95. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/equipment/__init__.py +0 -0
  96. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/equipment/armor.py +0 -0
  97. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/equipment/saddle.py +0 -0
  98. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/equipment/shield.py +0 -0
  99. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/equipment/weapon.py +0 -0
  100. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/misc/dino_owner.py +0 -0
  101. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/misc/inventory.py +0 -0
  102. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/misc/inventory_item.py +0 -0
  103. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/misc/object_crafter.py +0 -0
  104. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/misc/object_owner.py +0 -0
  105. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/misc/trait.py +0 -0
  106. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/stackables/__init__.py +0 -0
  107. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/stackables/_stackable.py +0 -0
  108. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/stackables/ammo.py +0 -0
  109. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/stackables/resource.py +0 -0
  110. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/object_model/structures/__init__.py +0 -0
  111. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/__init__.py +0 -0
  112. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_base_value_parser.py +0 -0
  113. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_base_value_validator.py +0 -0
  114. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_binary_reader_base.py +0 -0
  115. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_byte_operator.py +0 -0
  116. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_fast_shim.py +0 -0
  117. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/__init__.py +0 -0
  118. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/_property_insertor.py +0 -0
  119. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/_property_parser.py +0 -0
  120. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/_property_replacer.py +0 -0
  121. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/ark_binary_parser.py +0 -0
  122. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/ark_property.py +0 -0
  123. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/struct/__init__.py +0 -0
  124. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/struct/ark_dino_ancestor_entry.py +0 -0
  125. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/struct/ark_item_net_id.py +0 -0
  126. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/struct/ark_my_persistent_buff_datas.py +0 -0
  127. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/struct/ark_object_property.py +0 -0
  128. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/struct/ark_struct_type.py +0 -0
  129. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/struct/ark_tracked_actor_id_category_pair_with_bool.py +0 -0
  130. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/struct/ark_unique_net_id_repl.py +0 -0
  131. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/struct/ark_vector.py +0 -0
  132. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_legacy_parsing/struct/ark_vector_bool_pair.py +0 -0
  133. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_property_insertor.py +0 -0
  134. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_property_parser.py +0 -0
  135. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/_property_replacer.py +0 -0
  136. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/ark_binary_parser.py +0 -0
  137. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/ark_object.py +0 -0
  138. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/ark_property_container.py +0 -0
  139. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/ark_set.py +0 -0
  140. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/ark_value_type.py +0 -0
  141. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/array_property.py +0 -0
  142. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/game_object_reader_configuration.py +0 -0
  143. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/__init__.py +0 -0
  144. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_color.py +0 -0
  145. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_crafting_resource_requirement.py +0 -0
  146. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_dino_ancestor_entry.py +0 -0
  147. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_dino_order_id.py +0 -0
  148. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_gacha_resource_struct.py +0 -0
  149. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_gene_trait_struct.py +0 -0
  150. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_gigantoraptor_bonded_struct.py +0 -0
  151. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_int_point.py +0 -0
  152. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_item_craft_queue_entry.py +0 -0
  153. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_item_net_id.py +0 -0
  154. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_key_value_pair.py +0 -0
  155. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_linear_color.py +0 -0
  156. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_milestone_tree_level_and_index.py +0 -0
  157. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_my_persistent_buff_datas.py +0 -0
  158. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_object_property.py +0 -0
  159. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_painting_key_value.py +0 -0
  160. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_patrol_group_saved_data.py +0 -0
  161. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_player_death_reason.py +0 -0
  162. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_primal_saddle_structure.py +0 -0
  163. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_quat.py +0 -0
  164. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_rotator.py +2 -2
  165. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_server_custom_folder.py +0 -0
  166. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_struct_type.py +0 -0
  167. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_tracked_actor_id_category_pair.py +0 -0
  168. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_tracked_actor_id_category_pair_with_bool.py +0 -0
  169. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_tribe_alliance.py +0 -0
  170. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_tribe_rank_group.py +0 -0
  171. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_unique_net_id_repl.py +0 -0
  172. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_vector.py +0 -0
  173. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/ark_vector_bool_pair.py +0 -0
  174. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/object_reference.py +0 -0
  175. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/parsing/struct/unknown_struct.py +0 -0
  176. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/player/ark_character_config.py +0 -0
  177. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/player/ark_character_stats.py +0 -0
  178. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/player/ark_persistent_buff_data.py +0 -0
  179. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/player/ark_player.py +0 -0
  180. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/player/ark_tribute_item.py +0 -0
  181. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/saves/__init__.py +0 -0
  182. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/saves/header_location.py +0 -0
  183. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/saves/save_context.py +0 -0
  184. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/utils/__init__.py +0 -0
  185. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/utils/heatmap_visualization.py +0 -0
  186. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/utils/import_file.py +0 -0
  187. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/utils/json_utils.py +0 -0
  188. {arkparse-0.5.0 → arkparse-0.5.2}/src/arkparse/utils/map_images.py +0 -0
  189. {arkparse-0.5.0 → arkparse-0.5.2}/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.0
3
+ Version: 0.5.2
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.0"
7
+ version = "0.5.2"
8
8
  dependencies = [
9
9
  "rcon>=2.4.9",
10
10
  "numpy>=2.3.2",
@@ -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
@@ -43,7 +43,7 @@ class DinoApi:
43
43
  _DEFAULT_CONFIG = GameObjectReaderConfiguration(
44
44
  blueprint_name_filter=lambda name: \
45
45
  name is not None and \
46
- (("Dinos/" in name and "_Character_" in name) or \
46
+ (((("/Creatures/" in name) or ("/Dinos/" in name) or ("/SDinoVariants/" in name)) and "_Character_" in name) or \
47
47
  ("DinoCharacterStatusComponent" in name) or \
48
48
  ("PrimalItem_WeaponEmptyCryopod" in name or "PrimalItem_SCSCryopod" in name or "ItemDinoball.ItemDinoball_C" in name)))
49
49
 
@@ -222,7 +222,7 @@ class StructureApi:
222
222
 
223
223
  return result
224
224
 
225
- def remove_at_location(self, map: ArkMap, coords: MapCoords, radius: float = 0.3, owner_tribe_id: int = None, owner_tribe_name: str = None):
225
+ def remove_at_location(self, map: ArkMap, coords: MapCoords, radius: float = 0.3, owner_tribe_id: int | None = None, owner_tribe_name: str | None = None):
226
226
  structures = self.get_at_location(map, coords, radius)
227
227
 
228
228
  removed = []
@@ -236,7 +236,7 @@ class StructureApi:
236
236
 
237
237
  return removed
238
238
 
239
- def get_owned_by(self, owner: ObjectOwner = None, owner_tribe_id: int = None, owner_tribe_name: str = None) -> Dict[UUID, Union[Structure, StructureWithInventory]]:
239
+ def get_owned_by(self, owner: ObjectOwner = None, owner_tribe_id: int | None = None, owner_tribe_name: str | None = None) -> Dict[UUID, Union[Structure, StructureWithInventory]]:
240
240
  result = {}
241
241
 
242
242
  if owner is None and owner_tribe_id is None and owner_tribe_name is None:
@@ -299,32 +299,34 @@ class StructureApi:
299
299
  return result
300
300
 
301
301
  def get_connected_structures(self, structures: Dict[UUID, Union[Structure, StructureWithInventory]]) -> Dict[UUID, Union[Structure, StructureWithInventory]]:
302
+ from collections import deque
303
+
302
304
  result = structures.copy()
303
- new_found = True
304
- ignore = []
305
- processed = []
306
-
307
- while new_found:
308
- new_found = False
309
- new_result = result.copy()
310
- unprocessed = [s for s in result.values() if s.uuid not in processed]
311
- for s in unprocessed:
312
- if s.uuid in processed:
305
+ ignore = set()
306
+ processed = set()
307
+
308
+ # Initialize queue with all structures to process
309
+ queue = deque(structures.values())
310
+
311
+ while queue:
312
+ s = queue.popleft()
313
+
314
+ if s.uuid in processed:
315
+ continue
316
+ processed.add(s.uuid)
317
+
318
+ for uuid in s.linked_structure_uuids:
319
+ if uuid in result or uuid in ignore:
313
320
  continue
314
- for uuid in s.linked_structure_uuids:
315
- if uuid not in new_result.keys() and uuid not in ignore and uuid not in processed:
316
- new_found = True
317
- obj = self.get_by_id(uuid)
318
- if obj is not None:
319
- new_result[uuid] = obj
320
- else:
321
- ignore.append(uuid)
322
- ArkSaveLogger.api_log(f"Could not find linked structure {uuid}, ignoring")
323
- processed.append(s.uuid)
324
- result = new_result
325
-
326
- # ArkSaveLogger.api_log(f"Connected structures found so far: {len(result)}")
327
-
321
+
322
+ obj = self.get_by_id(uuid)
323
+ if obj is not None:
324
+ result[uuid] = obj
325
+ queue.append(obj)
326
+ else:
327
+ ignore.add(uuid)
328
+ ArkSaveLogger.api_log(f"Could not find linked structure {uuid}, ignoring")
329
+
328
330
  return result
329
331
 
330
332
  def modify_structures(self, structures: Dict[UUID, Union[Structure, StructureWithInventory]], new_owner: ObjectOwner = None, new_max_health: float = None):
@@ -79,13 +79,16 @@ class Alphas:
79
79
  alpha_tuso = "/Game/PrimalEarth/Dinos/Tusoteuthis/Mega_Tusoteuthis_Character_BP.Mega_Tusoteuthis_Character_BP_C"
80
80
  alpha_leedsichthys = "/Game/PrimalEarth/Dinos/Leedsichthys/Alpha_Leedsichthys_Character_BP.Alpha_Leedsichthys_Character_BP_C"
81
81
  alpha_fire_wyvern = "/Game/ScorchedEarth/Dinos/Wyvern/MegaWyvern_Character_BP_Fire.MegaWyvern_Character_BP_Fire_C"
82
+ alpha_revenant = "/Game/LostColony/Dinos/Zombie/MegaZombie_Character_BP_Hulking.MegaZombie_Character_BP_Hulking_C"
83
+ alpha_ossidon = "/Game/LostColony/Dinos/SnowMonster/MegaSnowMonster_Character_BP.MegaSnowMonster_Character_BP_C"
82
84
 
83
85
  paleo = PaleoAlphas()
84
86
 
85
87
  all_bps = [
86
88
  alpha_reaper_king, alpha_karkinos, alpha_basilisk,
87
89
  alpha_carnotaurus, alpha_megalodon, alpha_mosasaurus, alpha_raptor,
88
- alpha_deathworm, alpha_rex, alpha_tuso, alpha_leedsichthys, alpha_fire_wyvern
90
+ alpha_deathworm, alpha_rex, alpha_tuso, alpha_leedsichthys, alpha_fire_wyvern,
91
+ alpha_revenant
89
92
  ] + paleo.all_bps
90
93
 
91
94
  class Flyers:
@@ -377,6 +380,8 @@ class Dinos:
377
380
  queen_bee = "/Game/PrimalEarth/Dinos/Bee/Bee_Queen_Character_BP.Bee_Queen_Character_BP_C"
378
381
  rubble_golem = "/Game/ScorchedEarth/Dinos/RockGolem/RubbleGolem_Character_BP.RubbleGolem_Character_BP_C"
379
382
  helicoprion = "/Game/ASA/Dinos/Helicoprion/Helicoprion_Character_BP.Helicoprion_Character_BP_C"
383
+ acrocanthosaurus = "/Game/ASA/Dinos/Acrocanthosaurus/Acrocanthosaurus_Character_BP.Acrocanthosaurus_Character_BP_C"
384
+ cryolophosaurus = "/Game/ASA/Dinos/Cryolophosaurus/Cryolophosaurus_Character_BP.Cryolophosaurus_Character_BP_C"
380
385
 
381
386
  abberant = Abberant()
382
387
  paleo = Paleo()
@@ -411,7 +416,7 @@ class Dinos:
411
416
  dreadnoughtus, maelizard, shastasaurus, gacha, gasbag,
412
417
  managarmr, tek_raptor, tek_rex, tek_stego,
413
418
  velonosaur, yutyrannus, tek_parasaur, queen_bee,
414
- rubble_golem
419
+ rubble_golem, helicoprion, acrocanthosaurus, cryolophosaurus
415
420
  ] + abberant.all_bps + flyers.all_bps + \
416
421
  dlc_dinos.all_bps + shoulder_pets.all_bps + non_tameable.all_bps + \
417
422
  paleo.all_bps
@@ -118,6 +118,7 @@ class Saddles:
118
118
  pyromane: str = "/Game/ASA/Dinos/FireLion/PrimalItemArmor_Saddle_FireLion.PrimalItemArmor_Saddle_FireLion_C"
119
119
  crylophosaurus: str = "/Game/ASA/Dinos/Cryolophosaurus/Saddle/PrimalItemArmor_CryoSaddle.PrimalItemArmor_CryoSaddle_C"
120
120
  deinonychus: str = "/Game/Valguero/Dinos/Deinonychus/PrimalItemArmor_DeinonychusSaddle.PrimalItemArmor_DeinonychusSaddle_C"
121
+ acrocanthosaurus: str = "/Game/ASA/Dinos/Acrocanthosaurus/Saddle/PrimalItemArmor_AcroSaddle.PrimalItemArmor_AcroSaddle_C"
121
122
 
122
123
 
123
124
  all_bps = [yi_ling, archelon, ceratosaurus, deinosuchus, fasolasuchus, gigantoraptor_ASA,
@@ -135,7 +136,7 @@ class Saddles:
135
136
  thorny_dragon, bison, deinotherium, dreadnoughtus, maelizard, gacha, gas_bags,
136
137
  snow_owl, ravager, managarmr, velonosaur, helicoprion, gigantoraptor, desmodus,
137
138
  soulwyn, gigadesmodus_platform, gigadesmodus, maelwyn, aureliax, ossidon, megaraptor,
138
- pyromane, crylophosaurus, deinonychus]
139
+ pyromane, crylophosaurus, deinonychus, acrocanthosaurus]
139
140
 
140
141
  class Hazard:
141
142
  boots: str = "/Game/Aberration/CoreBlueprints/Items/Armor/HazardSuit/PrimalItemArmor_HazardSuitBoots.PrimalItemArmor_HazardSuitBoots_C"
@@ -332,7 +333,8 @@ class Advanced:
332
333
  chainsaw: str = "/Game/ScorchedEarth/WeaponChainsaw/PrimalItem_ChainSaw.PrimalItem_ChainSaw_C"
333
334
  flamethrower: str = "/Game/ScorchedEarth/WeaponFlamethrower/PrimalItem_WeapFlamethrower.PrimalItem_WeapFlamethrower_C"
334
335
  tek_spear: str = "/Game/LostColony/Weapons/TekSpear/PrimalItem_WeaponSpear_Tek.PrimalItem_WeaponSpear_Tek_C"
335
- all_bps = [compound_bow, fabricated_pistol, fabricated_shotgun, fabricated_sniper, fabricated_crossbow,longneck, assault_rifle, rocket_launcher, tek_rifle, chainsaw, flamethrower, tek_spear]
336
+ tek_sword: str = "/Game/PrimalEarth/CoreBlueprints/Weapons/PrimalItem_WeaponTekSword.PrimalItem_WeaponTekSword_C"
337
+ all_bps = [compound_bow, fabricated_pistol, fabricated_shotgun, fabricated_sniper, fabricated_crossbow,longneck, assault_rifle, rocket_launcher, tek_rifle, chainsaw, flamethrower, tek_spear, tek_sword]
336
338
 
337
339
  class CursedWeapons:
338
340
  chainsaw: str = "/Game/LostColony/CoreBlueprints/Items/CursedWeapons/PrimalItem_ChainSaw_Cursed.PrimalItem_ChainSaw_Cursed_C"
@@ -5,9 +5,14 @@ from zoneinfo import ZoneInfo
5
5
  from io import BytesIO
6
6
  from pathlib import Path
7
7
  import json
8
+ from typing import TYPE_CHECKING
9
+
10
+ if TYPE_CHECKING:
11
+ from arkparse.saves.asa_save import AsaSave
8
12
 
9
13
  from arkparse.enums import ArkMap
10
14
  from arkparse.logging import ArkSaveLogger
15
+ from arkparse.utils.tm_files import CONFIG_FILE_DIR
11
16
 
12
17
  SAVE_FILES_LOCATION = ["arksa", "ShooterGame", "Saved", "SavedArks"]
13
18
  INI_FOLDER_LOCATION = ["arksa", "ShooterGame", "Saved", "Config", "WindowsServer"]
@@ -82,7 +87,21 @@ class INI:
82
87
  GAME= "Game.ini"
83
88
 
84
89
  class ArkFtpClient:
85
- def __init__(self, host, port, user, password):
90
+ _LAST_FTP_CONFIG_PATH = CONFIG_FILE_DIR / "last_ftp_config.json"
91
+ _LAST_MAP_PATH = CONFIG_FILE_DIR / "last_map.txt"
92
+
93
+ def __init__(self, host = None, port = None, user = None, password = None):
94
+ self._configured_map = None
95
+ if host is None or port is None or user is None or password is None:
96
+ config, configured_map = self.load_configuration()
97
+ if config is None or map is None:
98
+ raise ValueError("FTP configuration not provided and no previous configuration found. Please provide host, port, user, and password or ensure the last configuration is saved. You can set the configuration using the set_configuration() method.")
99
+ host = config['host']
100
+ port = config['port']
101
+ user = config['user']
102
+ password = config['password']
103
+ self._configured_map = configured_map
104
+
86
105
  self.host = host
87
106
  self.port = port
88
107
  self.user = user
@@ -91,8 +110,37 @@ class ArkFtpClient:
91
110
  self.connected = False
92
111
  self.ftp.connect(host, port, timeout=10)
93
112
  self.ftp.login(user, password)
94
- self.map = None
95
113
  self.connected = True
114
+ self.map = None
115
+ if self._configured_map is not None:
116
+ self.set_map(self._configured_map)
117
+
118
+ @staticmethod
119
+ def set_configuration(host, port, user, password, map: ArkMap):
120
+ config = {
121
+ "host": host,
122
+ "port": port,
123
+ "user": user,
124
+ "password": password
125
+ }
126
+ with open(ArkFtpClient._LAST_FTP_CONFIG_PATH, 'w') as config_file:
127
+ json.dump(config, config_file)
128
+ with open(ArkFtpClient._LAST_MAP_PATH, 'w') as map_file:
129
+ map_file.write(str(map.value))
130
+
131
+ @staticmethod
132
+ def load_configuration():
133
+ if not ArkFtpClient._LAST_FTP_CONFIG_PATH.exists() or not ArkFtpClient._LAST_MAP_PATH.exists():
134
+ return None, None
135
+
136
+ with open(ArkFtpClient._LAST_FTP_CONFIG_PATH, 'r') as config_file:
137
+ config = json.load(config_file)
138
+
139
+ with open(ArkFtpClient._LAST_MAP_PATH, 'r') as map_file:
140
+ map_value = map_file.read().strip()
141
+ map = ArkMap(int(map_value))
142
+
143
+ return config, map
96
144
 
97
145
  @staticmethod
98
146
  def from_config(config, map: ArkMap=None):
@@ -276,6 +324,13 @@ class ArkFtpClient:
276
324
  self.download_file(file_name, local_file)
277
325
  return local_file
278
326
 
327
+ def get_current_save(self, map: ArkMap = None) -> "AsaSave":
328
+ from arkparse import AsaSave
329
+ map = map if map is not None else self._configured_map
330
+ save_contents = self.download_save_file(output_directory=None, map=map)
331
+ save = AsaSave(contents=save_contents, map=map)
332
+ return save
333
+
279
334
  def remove_save_file(self, map: ArkMap = None):
280
335
  map: dict = self._check_map(map)
281
336
  self.__nav_to_save_files(map)
@@ -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.
@@ -220,8 +220,10 @@ class ArkGameObject(ArkPropertyContainer):
220
220
  # self.uuid2 = reader.read_uuid()
221
221
 
222
222
  def print_properties(self):
223
+ ArkSaveLogger.set_log_level(ArkSaveLogger.LogTypes.INFO, True)
223
224
  ArkSaveLogger.info_log(f"Properties for {self.blueprint} ({self.uuid}):")
224
225
  super().print_properties()
226
+ ArkSaveLogger.set_log_level(ArkSaveLogger.LogTypes.INFO, False)
225
227
 
226
228
  def read_double(self, reader: ArkBinaryParser, property_name: str) -> float:
227
229
  reader.validate_name(property_name)
@@ -146,9 +146,13 @@ class Base:
146
146
  ArkSaveLogger.objects_log(f"Padding {turret.get_short_name()} ({turret.object.uuid}) to {amount} bullets")
147
147
  self.__set_new_inventory(save, turret, bullet, amount)
148
148
 
149
+ # Correct NumBullets prop
150
+ prop = turret.object.find_property("NumBullets")
151
+ if prop is not None:
152
+ turret.binary.replace_u32(prop, amount)
153
+
149
154
  ArkSaveLogger.objects_log(f"Updating {turret.get_short_name()} and inventory in database")
150
155
  turret.update_binary()
151
- turret.inventory.update_binary()
152
156
 
153
157
  return len(turrets)
154
158
 
@@ -5,8 +5,9 @@ import random
5
5
 
6
6
  from arkparse.object_model.misc.__parsed_object_base import ParsedObjectBase
7
7
  from arkparse.saves.asa_save import AsaSave
8
- from arkparse.parsing.struct.actor_transform import ActorTransform
8
+ from arkparse.parsing.struct.actor_transform import ActorTransform, MapCoords
9
9
  from arkparse.parsing.struct.ark_vector import ArkVector
10
+ from arkparse.parsing.struct.ark_rotator import ArkRotator
10
11
  from arkparse.object_model.ark_game_object import ArkGameObject
11
12
  from arkparse.enums import ArkDinoTrait
12
13
  from arkparse.utils.json_utils import DefaultJsonEncoder
@@ -38,6 +39,12 @@ class GeneTrait:
38
39
 
39
40
  def __str__(self):
40
41
  return f"{self.trait.value}[{self.level}]"
42
+
43
+ def __eq__(self, other):
44
+ if not isinstance(other, GeneTrait):
45
+ return False
46
+
47
+ return self.trait == other.trait and self.level == other.level
41
48
 
42
49
  class Dino(ParsedObjectBase):
43
50
  id_: DinoId = None
@@ -51,6 +58,7 @@ class Dino(ParsedObjectBase):
51
58
  gene_traits: List[GeneTrait] = []
52
59
  stats: DinoStats = DinoStats()
53
60
  _location: ActorTransform = ActorTransform()
61
+ _rotation: ArkRotator = None
54
62
 
55
63
  #saddle: Saddle
56
64
  def __init_props__(self):
@@ -82,11 +90,34 @@ class Dino(ParsedObjectBase):
82
90
  return False
83
91
 
84
92
  return self.object.uuid == other.object.uuid and self.id_ == other.id_
85
-
93
+
86
94
  @property
87
95
  def location(self) -> ActorTransform:
96
+ if self._rotation is None:
97
+ full_location = self.save.get_actor_transform(self.object.uuid)
98
+ if full_location is not None:
99
+ self._location = full_location
100
+ self._rotation = ArkRotator(pitch=self._location.pitch, roll=self._location.roll, yaw=self._location.yaw)
88
101
  return self._location
102
+
103
+ @property
104
+ def rotation(self) -> ArkRotator:
105
+ if self._rotation is not None:
106
+ return self._rotation
107
+ full_location = self.save.get_actor_transform(self.object.uuid)
108
+ if full_location is not None:
109
+ self._location = full_location
110
+ self._rotation = ArkRotator(pitch=self._location.pitch, roll=self._location.roll, yaw=self._location.yaw)
111
+ return ArkRotator(pitch=self._location.pitch, roll=self._location.roll, yaw=self._location.yaw)
89
112
 
113
+ @property
114
+ def map_coordinates(self) -> MapCoords:
115
+ location = self.location
116
+ if location is not None:
117
+ return location.as_map_coords(self.save.map)
118
+ else:
119
+ return None
120
+
90
121
  @staticmethod
91
122
  def from_object(dino_obj: ArkGameObject, status_obj: ArkGameObject, dino: "Dino" = None):
92
123
  if dino is not None:
@@ -101,6 +132,12 @@ class Dino(ParsedObjectBase):
101
132
 
102
133
  return d
103
134
 
135
+ def __eq__(self, other):
136
+ if not isinstance(other, Dino):
137
+ return False
138
+
139
+ return self.id_ == other.id_
140
+
104
141
  def remove_from_save(self):
105
142
  self.save.remove_obj_from_db(self.stats.uuid)
106
143
 
@@ -283,6 +320,7 @@ class Dino(ParsedObjectBase):
283
320
  self.save.modify_actor_transform(self.object.uuid, location.to_bytes())
284
321
  self.update_binary()
285
322
  self._location = location
323
+ self._rotation = ArkRotator(pitch=location.pitch, roll=location.roll, yaw=location.yaw)
286
324
 
287
325
  def heal(self):
288
326
  self.stats.heal()
@@ -27,6 +27,7 @@ class TamedDino(Dino):
27
27
  tamed_name: str
28
28
  percentage_imprinted: float
29
29
  cryopod: "Cryopod"
30
+ neutered: bool
30
31
 
31
32
  @property
32
33
  def percentage_imprinted(self):
@@ -47,9 +48,11 @@ class TamedDino(Dino):
47
48
  super().__init_props__()
48
49
 
49
50
  self.cryopod = None
50
- self.tamed_name = self.object.get_property_value("TamedName")
51
+ self.tamed_name = self.object.get_property_value("TamedName", "NONE")
51
52
  inv_uuid: ObjectReference = self.object.get_property_value("MyInventoryComponent")
52
53
  self.owner = DinoOwner(self.object)
54
+ self.neutered = self.object.get_property_value("bNeutered", False)
55
+
53
56
 
54
57
  if inv_uuid is None:
55
58
  self.inv_uuid = None
@@ -139,10 +142,10 @@ class TamedDino(Dino):
139
142
  def store_binary(self, path: Path, name = None, prefix = "obj_", no_suffix=False, force_inventory=False):
140
143
  if self.inventory is None and force_inventory:
141
144
  raise ValueError("Cannot store TamedDino without inventory.")
142
- print(self.inventory)
145
+ # print(self.inventory)
143
146
  if self.inventory is not None:
144
147
  self.inventory.store_binary(path, name, no_suffix=no_suffix)
145
- print(f"Storing TamedDino {self.object.uuid} at {path}")
148
+ # print(f"Storing TamedDino {self.object.uuid} at {path}")
146
149
  return super().store_binary(path, name, prefix, no_suffix)
147
150
 
148
151
  def to_json_obj(self):
@@ -168,6 +171,12 @@ class TamedDino(Dino):
168
171
  self.inventory.add_item(item)
169
172
  return True
170
173
 
174
+ def set_neutered(self, neutered: bool):
175
+ self.binary.replace_boolean(self.object.find_property("bNeutered"), neutered)
176
+ self.neutered = neutered
177
+ self.update_binary()
178
+ self.update_object()
179
+
171
180
  def remove_item(self, item: UUID):
172
181
  self.inventory.remove_item(item)
173
182
  self.update_binary()
@@ -24,6 +24,10 @@ class ParsedObjectBase:
24
24
  @property
25
25
  def blueprint(self) -> str:
26
26
  return self.object.blueprint if self.object is not None else None
27
+
28
+ @property
29
+ def short_name(self) -> str:
30
+ return self.object.get_short_name() if self.object is not None else None
27
31
 
28
32
  def __init_props__(self):
29
33
  pass
@@ -10,7 +10,7 @@ from arkparse.object_model.misc.__parsed_object_base import ParsedObjectBase
10
10
  from arkparse.object_model.misc.object_owner import ObjectOwner
11
11
  from arkparse.parsing import ArkBinaryParser
12
12
  from arkparse.parsing.struct.object_reference import ObjectReference
13
- from arkparse.parsing.struct import ActorTransform
13
+ from arkparse.parsing.struct import ActorTransform, MapCoords
14
14
  from arkparse import AsaSave
15
15
  from arkparse.utils.json_utils import DefaultJsonEncoder
16
16
 
@@ -156,6 +156,12 @@ class Structure(ParsedObjectBase):
156
156
  for linked_structure in self.linked_structure_uuids:
157
157
  result.append(linked_structure.__str__())
158
158
  return result
159
+
160
+ @property
161
+ def map_coordinates(self) -> MapCoords:
162
+ if self.location is not None:
163
+ return self.location.as_map_coords(self.save.map)
164
+ return None
159
165
 
160
166
  def to_json_obj(self):
161
167
  # Grab already set properties
@@ -26,7 +26,7 @@ class StructureWithInventory(Structure):
26
26
  inv_uuid = self.object.get_property_value("MyInventoryComponent")
27
27
  self.inventory_uuid = UUID(inv_uuid.value) if inv_uuid is not None else None
28
28
  self.item_count = self.object.get_property_value("CurrentItemCount", default=0)
29
- self.max_item_count = self.object.get_property_value("MaxItemCount")
29
+ self.max_item_count = self.object.get_property_value("MaxItemCount", default=1)
30
30
 
31
31
  if self.inventory_uuid is not None and not bypass_inventory:
32
32
  self._inventory = Inventory(self.inventory_uuid, save=self.save)
@@ -36,6 +36,14 @@ class StructureWithInventory(Structure):
36
36
  if self._inventory is None and self.inventory_uuid is not None:
37
37
  self._inventory = Inventory(self.inventory_uuid, save=self.save)
38
38
  return self._inventory
39
+
40
+ @property
41
+ def open_slots(self) -> int:
42
+ return self.max_item_count - self.item_count
43
+
44
+ @property
45
+ def is_empty(self) -> bool:
46
+ return self.item_count == 0
39
47
 
40
48
  def set_item_quantity(self, quantity: int):
41
49
  if self.item_count != None:
@@ -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