arkparse 0.5.2__tar.gz → 0.5.4__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.
- {arkparse-0.5.2 → arkparse-0.5.4}/PKG-INFO +1 -1
- {arkparse-0.5.2 → arkparse-0.5.4}/pyproject.toml +1 -1
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/api/json_api.py +6 -1
- arkparse-0.5.4/src/arkparse/assets/GENESIS_Ocean.png +0 -0
- arkparse-0.5.4/src/arkparse/assets/GENESIS_OtherBiomes.png +0 -0
- arkparse-0.5.4/src/arkparse/assets/make_composite.py +171 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/classes/dinos.py +10 -3
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/classes/placed_structures.py +5 -2
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/enums/ark_map.py +9 -1
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/ark_game_object.py +24 -4
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/dinos/dino.py +1 -1
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_base_value_parser.py +2 -1
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/ark_property.py +58 -24
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/__init__.py +1 -0
- arkparse-0.5.4/src/arkparse/parsing/struct/actor_transform.py +423 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_struct_type.py +3 -0
- arkparse-0.5.4/src/arkparse/parsing/struct/ark_vector2d.py +38 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/saves/save_connection.py +8 -5
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/utils/heatmap_visualization.py +4 -3
- arkparse-0.5.2/src/arkparse/parsing/struct/actor_transform.py +0 -412
- {arkparse-0.5.2 → arkparse-0.5.4}/.gitignore +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/LICENSE +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/README.md +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/api/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/api/base_api.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/api/dino_api.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/api/equipment_api.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/api/general_api.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/api/player_api.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/api/rcon_api.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/api/stackable_api.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/api/structure_api.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/ark_tribe.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/ABERRATION.PNG +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/LOST_COLONY.PNG +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/RAGNAROK.PNG +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/THE_ISLAND.PNG +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/heavy_inventory +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/tamable_dinos.txt +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/armor +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/armor_bp +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/armor_bp_n.json +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/armor_n.json +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/saddle +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/saddle_bp +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/saddle_bp_n.json +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/saddle_n.json +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/shield +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/shield_bp +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/shield_bp_n.json +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/shield_n.json +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/weapon +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/weapon_bp +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/weapon_bp_n.json +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/equipment/weapon_n.json +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/inventory/with_item_n.json +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/stackable/stackable +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/stackable/stackable_n.json +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/trait/trait +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/assets/templates/trait/trait_n.json +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/classes/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/classes/consumables.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/classes/equipment.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/classes/player.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/classes/resources.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/classes/traits.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/enums/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/enums/ark_dino_trait.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/enums/ark_enum.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/enums/ark_equipment_stat.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/enums/ark_item_quality.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/enums/ark_stat.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/ftp/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/ftp/ark_ftp_client.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/helpers/dino/is_wild_tamed.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/logging/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/logging/ark_save_logger.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/bases/base.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/cluster_data/ark_cluster_data.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/cluster_data/cluster_data_dino.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/cluster_data/cluster_data_item.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/cryopods/cryopod.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/dinos/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/dinos/baby.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/dinos/dino_ai_controller.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/dinos/dino_id.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/dinos/pedigree.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/dinos/stats.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/dinos/tamed_baby.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/dinos/tamed_dino.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/equipment/__armor_defaults.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/equipment/__equipment.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/equipment/__equipment_with_armor.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/equipment/__equipment_with_durability.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/equipment/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/equipment/armor.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/equipment/saddle.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/equipment/shield.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/equipment/weapon.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/misc/__parsed_object_base.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/misc/dino_owner.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/misc/inventory.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/misc/inventory_item.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/misc/object_crafter.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/misc/object_owner.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/misc/trait.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/stackables/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/stackables/_stackable.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/stackables/ammo.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/stackables/resource.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/structures/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/structures/structure.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/object_model/structures/structure_with_inventory.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_base_value_validator.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_binary_reader_base.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_byte_operator.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_fast_shim.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/_property_insertor.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/_property_parser.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/_property_replacer.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/ark_binary_parser.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/ark_property.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/struct/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/struct/ark_dino_ancestor_entry.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/struct/ark_item_net_id.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/struct/ark_my_persistent_buff_datas.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/struct/ark_object_property.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/struct/ark_struct_type.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/struct/ark_tracked_actor_id_category_pair_with_bool.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/struct/ark_unique_net_id_repl.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/struct/ark_vector.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_legacy_parsing/struct/ark_vector_bool_pair.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_property_insertor.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_property_parser.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/_property_replacer.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/ark_archive.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/ark_binary_parser.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/ark_object.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/ark_property_container.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/ark_set.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/ark_value_type.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/array_property.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/game_object_reader_configuration.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_color.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_crafting_resource_requirement.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_custom_item_data.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_dino_ancestor_entry.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_dino_order_id.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_gacha_resource_struct.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_gene_trait_struct.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_gigantoraptor_bonded_struct.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_int_point.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_item_craft_queue_entry.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_item_net_id.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_key_value_pair.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_linear_color.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_milestone_tree_level_and_index.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_my_persistent_buff_datas.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_object_property.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_painting_key_value.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_patrol_group_saved_data.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_player_death_reason.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_primal_saddle_structure.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_quat.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_rotator.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_server_custom_folder.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_tracked_actor_id_category_pair.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_tracked_actor_id_category_pair_with_bool.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_tribe_alliance.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_tribe_rank_group.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_unique_net_id_repl.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_vector.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/ark_vector_bool_pair.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/object_reference.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/parsing/struct/unknown_struct.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/player/ark_character_config.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/player/ark_character_stats.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/player/ark_persistent_buff_data.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/player/ark_player.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/player/ark_tribute_item.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/saves/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/saves/asa_save.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/saves/header_location.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/saves/save_context.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/utils/__init__.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/utils/import_file.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/utils/json_utils.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/utils/map_images.py +0 -0
- {arkparse-0.5.2 → arkparse-0.5.4}/src/arkparse/utils/tm_files.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arkparse
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.4
|
|
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>
|
|
@@ -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
|
-
|
|
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 \
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
make_composite.py
|
|
4
|
+
|
|
5
|
+
Downloads map tiles from a tile server and composites them into a single image.
|
|
6
|
+
Auto-detects grid size using binary search.
|
|
7
|
+
|
|
8
|
+
Requires: Pillow (PIL)
|
|
9
|
+
pip install pillow
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import io
|
|
14
|
+
import os
|
|
15
|
+
import sys
|
|
16
|
+
from typing import List
|
|
17
|
+
from urllib.request import urlopen, Request
|
|
18
|
+
from urllib.error import HTTPError
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
from PIL import Image
|
|
23
|
+
except Exception as e:
|
|
24
|
+
print("Pillow is required: pip install pillow", file=sys.stderr)
|
|
25
|
+
raise
|
|
26
|
+
|
|
27
|
+
# Headers to mimic a browser request
|
|
28
|
+
HEADERS = {
|
|
29
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
30
|
+
"Accept": "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",
|
|
31
|
+
"Referer": "https://wikily.gg/",
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
TILE_SIZE = 256
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def tile_exists(base_url: str, zoom: int, x: int, y: int) -> bool:
|
|
38
|
+
"""Check if a tile exists at the given coordinates."""
|
|
39
|
+
url = f"{base_url}/{zoom}/{x}/{y}.png"
|
|
40
|
+
try:
|
|
41
|
+
req = Request(url, headers=HEADERS, method='HEAD')
|
|
42
|
+
with urlopen(req, timeout=10) as resp:
|
|
43
|
+
return resp.status == 200
|
|
44
|
+
except HTTPError:
|
|
45
|
+
return False
|
|
46
|
+
except Exception:
|
|
47
|
+
# Try GET as fallback (some servers don't support HEAD)
|
|
48
|
+
try:
|
|
49
|
+
req = Request(url, headers=HEADERS)
|
|
50
|
+
with urlopen(req, timeout=10) as resp:
|
|
51
|
+
return resp.status == 200
|
|
52
|
+
except:
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def find_grid_size(base_url: str, zoom: int) -> int:
|
|
57
|
+
"""
|
|
58
|
+
Binary search to find the grid size (number of tiles per side).
|
|
59
|
+
Assumes square grid starting at 0,0.
|
|
60
|
+
"""
|
|
61
|
+
print(f"Detecting grid size for zoom {zoom}...")
|
|
62
|
+
|
|
63
|
+
# First, verify tile 0,0 exists
|
|
64
|
+
if not tile_exists(base_url, zoom, 0, 0):
|
|
65
|
+
raise SystemExit(f"Tile 0,0 does not exist at {base_url}/{zoom}/")
|
|
66
|
+
|
|
67
|
+
# Binary search for max coordinate
|
|
68
|
+
low, high = 1, 256 # reasonable upper bound
|
|
69
|
+
|
|
70
|
+
# First find an upper bound that doesn't exist
|
|
71
|
+
while tile_exists(base_url, zoom, high - 1, 0):
|
|
72
|
+
high *= 2
|
|
73
|
+
if high > 1024:
|
|
74
|
+
raise SystemExit("Grid size exceeds reasonable limit (1024)")
|
|
75
|
+
|
|
76
|
+
# Binary search
|
|
77
|
+
while low < high:
|
|
78
|
+
mid = (low + high) // 2
|
|
79
|
+
if tile_exists(base_url, zoom, mid, 0):
|
|
80
|
+
low = mid + 1
|
|
81
|
+
else:
|
|
82
|
+
high = mid
|
|
83
|
+
|
|
84
|
+
grid_size = low
|
|
85
|
+
print(f"Detected grid size: {grid_size}x{grid_size} tiles")
|
|
86
|
+
return grid_size
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def download_image(url: str) -> Image.Image:
|
|
90
|
+
"""Download an image from URL and return as PIL Image."""
|
|
91
|
+
req = Request(url, headers=HEADERS)
|
|
92
|
+
with urlopen(req, timeout=30) as resp:
|
|
93
|
+
data = resp.read()
|
|
94
|
+
return Image.open(io.BytesIO(data)).convert("RGBA")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def compose_map(base_url: str, zoom: int, out_path: str) -> None:
|
|
98
|
+
"""Download all tiles for a zoom level and compose into single image."""
|
|
99
|
+
grid_size = find_grid_size(base_url, zoom)
|
|
100
|
+
|
|
101
|
+
width = grid_size * TILE_SIZE
|
|
102
|
+
height = grid_size * TILE_SIZE
|
|
103
|
+
total_tiles = grid_size * grid_size
|
|
104
|
+
|
|
105
|
+
print(f"Canvas size: {width}x{height} ({total_tiles} tiles)")
|
|
106
|
+
|
|
107
|
+
canvas = Image.new("RGBA", (width, height), (0, 0, 0, 0))
|
|
108
|
+
|
|
109
|
+
downloaded = 0
|
|
110
|
+
failed = 0
|
|
111
|
+
|
|
112
|
+
for y in range(grid_size):
|
|
113
|
+
for x in range(grid_size):
|
|
114
|
+
tile_num = y * grid_size + x + 1
|
|
115
|
+
url = f"{base_url}/{zoom}/{x}/{y}.png"
|
|
116
|
+
print(f"Downloading tile {tile_num}/{total_tiles}: {zoom}/{x}/{y}.png", end="")
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
img = download_image(url)
|
|
120
|
+
if img.size != (TILE_SIZE, TILE_SIZE):
|
|
121
|
+
img = img.resize((TILE_SIZE, TILE_SIZE))
|
|
122
|
+
|
|
123
|
+
paste_x = x * TILE_SIZE
|
|
124
|
+
paste_y = y * TILE_SIZE
|
|
125
|
+
canvas.paste(img, (paste_x, paste_y))
|
|
126
|
+
downloaded += 1
|
|
127
|
+
print(" OK")
|
|
128
|
+
except Exception as e:
|
|
129
|
+
print(f" FAILED: {e}")
|
|
130
|
+
failed += 1
|
|
131
|
+
|
|
132
|
+
print(f"\nDownloaded: {downloaded}, Failed: {failed}")
|
|
133
|
+
|
|
134
|
+
# Save
|
|
135
|
+
os.makedirs(os.path.dirname(out_path) or ".", exist_ok=True)
|
|
136
|
+
canvas.convert("RGB").save(out_path, format="PNG")
|
|
137
|
+
print(f"Saved -> {out_path}")
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def main() -> None:
|
|
141
|
+
# Configuration
|
|
142
|
+
output_dir = Path(__file__).parent
|
|
143
|
+
zoom = 5
|
|
144
|
+
|
|
145
|
+
# List of maps to download: (base_url, output_name)
|
|
146
|
+
maps: List[tuple[str, str]] = [
|
|
147
|
+
("https://r2.wikily.gg/images/ark/maps/lost_colony_tiles", "LOST_COLONY.png"),
|
|
148
|
+
("https://r2.wikily.gg/images/ark/maps/valguero_tiles", "VALGUERO.png"),
|
|
149
|
+
("https://r2.wikily.gg/images/ark/maps/aberration_tiles", "ABERRATION.png"),
|
|
150
|
+
("https://r2.wikily.gg/images/ark/maps/ragnarok_tiles", "RAGNAROK.png"),
|
|
151
|
+
("https://r2.wikily.gg/images/ark/maps/the_island_tiles", "THE_ISLAND.png"),
|
|
152
|
+
("https://r2.wikily.gg/images/ark/maps/genesis_tiles", "GENESIS_BIOMES.png"),
|
|
153
|
+
("https://r2.wikily.gg/images/ark/maps/genesisocean_tiles", "GENESIS_OCEAN.png"),
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
for base_url, output_name in maps:
|
|
157
|
+
print(f"\n{'='*60}")
|
|
158
|
+
print(f"Processing: {output_name}")
|
|
159
|
+
print(f"Base URL: {base_url}")
|
|
160
|
+
print(f"Zoom: {zoom}")
|
|
161
|
+
print('='*60)
|
|
162
|
+
|
|
163
|
+
out_path = os.path.join(output_dir, output_name)
|
|
164
|
+
try:
|
|
165
|
+
compose_map(base_url, zoom, out_path)
|
|
166
|
+
except Exception as e:
|
|
167
|
+
print(f"ERROR processing {output_name}: {e}", file=sys.stderr)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
if __name__ == "__main__":
|
|
171
|
+
main()
|
|
@@ -139,7 +139,11 @@ class DlcDinos:
|
|
|
139
139
|
malwyn = "/Game/LostColony/Dinos/SnowDragon/SnowDragon_Character_BP.SnowDragon_Character_BP_C"
|
|
140
140
|
ossidon = "/Game/LostColony/Dinos/SnowMonster/SnowMonster_Character_BP.SnowMonster_Character_BP_C"
|
|
141
141
|
gloon = "/Game/LostColony/Dinos/LostChargePet/LostCharge_LanternPet_Char_BP.LostCharge_LanternPet_Char_BP_C"
|
|
142
|
-
|
|
142
|
+
lumina = "/Game/Dragontopia/Dragons/Eclipsar/Lumina/Lumina_Character_BP.Lumina_Character_BP_C"
|
|
143
|
+
umbra = "/Game/Dragontopia/Dragons/Eclipsar/Umbra/Umbra_Character_BP.Umbra_Character_BP_C"
|
|
144
|
+
brig_ship = "/Game/Water/Vessels/Brig/BrigShipBP.BrigShipBP_C"
|
|
145
|
+
sloop_ship = "/Game/Water/Vessels/Sloop/SloopShipBP.SloopShipBP_C"
|
|
146
|
+
all_bps = [firemane, archelon, dread_mare, oasisaur, train, helper_bot, zeppelin, doggo, veilwyn, elderclaw, solwyn, malwyn, ossidon, gloon, lumina, umbra, brig_ship, sloop_ship]
|
|
143
147
|
|
|
144
148
|
class ShoulderPets:
|
|
145
149
|
glowtail = "/Game/Aberration/Dinos/LanternLizard/LanternLizard_Character_BP.LanternLizard_Character_BP_C"
|
|
@@ -223,6 +227,8 @@ class NonTameable:
|
|
|
223
227
|
tek_giga = "/Game/PrimalEarth/Dinos/Giganotosaurus/BionicGigant_Character_BP.BionicGigant_Character_BP_C"
|
|
224
228
|
leedsichthys = "/Game/PrimalEarth/Dinos/Leedsichthys/Leedsichthys_Character_BP.Leedsichthys_Character_BP_C"
|
|
225
229
|
yeti = "/Game/PrimalEarth/Dinos/Bigfoot/Yeti_Character_BP.Yeti_Character_BP_C"
|
|
230
|
+
insect_swarm = "/Game/Genesis/Dinos/Swarms/InsectSwarmChar_BP.InsectSwarmChar_BP_C"
|
|
231
|
+
microbe_swarm = "/Game/Genesis/Dinos/Swarms/MicrobeSwarmChar_BP.MicrobeSwarmChar_BP_C"
|
|
226
232
|
corrupted = Corrupted()
|
|
227
233
|
alpha = Alphas()
|
|
228
234
|
event = event()
|
|
@@ -233,7 +239,7 @@ class NonTameable:
|
|
|
233
239
|
coelacanth_ocean, leech, leech_diseased, piranha,
|
|
234
240
|
sabertooth_salmon, trilobite, death_worm, jugbug_oil, jugbug_water,
|
|
235
241
|
enforcer, scout, defence_unit, polar_bear, iceworm, tek_giga,
|
|
236
|
-
leedsichthys, yeti
|
|
242
|
+
leedsichthys, yeti, insect_swarm, microbe_swarm
|
|
237
243
|
] + corrupted.all_bps + alpha.all_bps + event.all_bps
|
|
238
244
|
|
|
239
245
|
class Paleo:
|
|
@@ -382,6 +388,7 @@ class Dinos:
|
|
|
382
388
|
helicoprion = "/Game/ASA/Dinos/Helicoprion/Helicoprion_Character_BP.Helicoprion_Character_BP_C"
|
|
383
389
|
acrocanthosaurus = "/Game/ASA/Dinos/Acrocanthosaurus/Acrocanthosaurus_Character_BP.Acrocanthosaurus_Character_BP_C"
|
|
384
390
|
cryolophosaurus = "/Game/ASA/Dinos/Cryolophosaurus/Cryolophosaurus_Character_BP.Cryolophosaurus_Character_BP_C"
|
|
391
|
+
magmasaur = "/Game/Genesis/Dinos/Cherufe/Cherufe_Character_BP"
|
|
385
392
|
|
|
386
393
|
abberant = Abberant()
|
|
387
394
|
paleo = Paleo()
|
|
@@ -416,7 +423,7 @@ class Dinos:
|
|
|
416
423
|
dreadnoughtus, maelizard, shastasaurus, gacha, gasbag,
|
|
417
424
|
managarmr, tek_raptor, tek_rex, tek_stego,
|
|
418
425
|
velonosaur, yutyrannus, tek_parasaur, queen_bee,
|
|
419
|
-
rubble_golem, helicoprion, acrocanthosaurus, cryolophosaurus
|
|
426
|
+
rubble_golem, helicoprion, acrocanthosaurus, cryolophosaurus, magmasaur
|
|
420
427
|
] + abberant.all_bps + flyers.all_bps + \
|
|
421
428
|
dlc_dinos.all_bps + shoulder_pets.all_bps + non_tameable.all_bps + \
|
|
422
429
|
paleo.all_bps
|
|
@@ -96,8 +96,9 @@ class Crafting:
|
|
|
96
96
|
cooking_pot = "/Game/PrimalEarth/Structures/CookingPot.CookingPot_C"
|
|
97
97
|
grill = "/Game/PrimalEarth/Structures/Grill.Grill_C"
|
|
98
98
|
chembench = "/Game/PrimalEarth/Structures/StorageBox_ChemBench.StorageBox_ChemBench_C"
|
|
99
|
+
blood_forge = "/Game/LostColony/Structures/Bloodforge/Inventory/InventoryComponent_Bloodforge.InventoryComponent_Bloodforge_C"
|
|
99
100
|
|
|
100
|
-
all_bps = [forge, mortar_and_pestle, compost_bin, campfire, cooking_pot, grill, chembench]
|
|
101
|
+
all_bps = [forge, mortar_and_pestle, compost_bin, campfire, cooking_pot, grill, chembench, blood_forge]
|
|
101
102
|
|
|
102
103
|
class Utility:
|
|
103
104
|
simple_bed = "/Game/PrimalEarth/Structures/SimpleBed.SimpleBed_C"
|
|
@@ -112,9 +113,11 @@ class Utility:
|
|
|
112
113
|
toilet = "/Game/PrimalEarth/Structures/Furniture/StructureBP_Toilet.StructureBP_Toilet_C"
|
|
113
114
|
cryofridge = "/Game/Extinction/Structures/Cryofridge/CryoFridge.CryoFridge_C"
|
|
114
115
|
deathitemcache = "/Game/PrimalEarth/Structures/DeathItemCache.DeathItemCache_C"
|
|
116
|
+
cryo_hospital = "/Game/LostColony/Structures/CryoHospital/Inventory/InventoryComponent_CryoHospital.InventoryComponent_CryoHospital_C"
|
|
117
|
+
medical_stand = "/Game/LostColony/Structures/MedicalStand/Inventories/InventoryComponent_MedicalStand.InventoryComponent_MedicalStand_C"
|
|
115
118
|
|
|
116
119
|
all_bps = [simple_bed, sleeping_bag, anvil_bench, small_storage_box, large_bear_trap, large_storage_box,
|
|
117
|
-
bunk_bed, vault, sleeping_pod, toilet, cryofridge, deathitemcache]
|
|
120
|
+
bunk_bed, vault, sleeping_pod, toilet, cryofridge, deathitemcache, cryo_hospital, medical_stand]
|
|
118
121
|
|
|
119
122
|
class TributeTerminals:
|
|
120
123
|
tribute_terminal_purple = "/Game/PrimalEarth/Structures/TributeTerminal_Purple.TributeTerminal_Purple_C"
|
|
@@ -15,10 +15,18 @@ class ArkMap(Enum):
|
|
|
15
15
|
SVARTALFHEIM = 11
|
|
16
16
|
CLUB_ARK = 12
|
|
17
17
|
LOST_COLONY = 13
|
|
18
|
+
GENESIS1 = 14
|
|
18
19
|
|
|
19
20
|
def to_file_name(self) -> str:
|
|
20
21
|
"""
|
|
21
22
|
Converts the enum value to a file name.
|
|
22
23
|
:return: The file name of the map.
|
|
23
24
|
"""
|
|
24
|
-
return self.name.replace('_', ' ').title().replace(' ', '')
|
|
25
|
+
return self.name.replace('_', ' ').title().replace(' ', '')
|
|
26
|
+
|
|
27
|
+
class SubMap(Enum):
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
class GenesisSubMap(Enum):
|
|
31
|
+
BIOMES = "OtherBiomes"
|
|
32
|
+
OCEAN = "Ocean"
|
|
@@ -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 = [
|
|
@@ -267,7 +267,7 @@ class Dino(ParsedObjectBase):
|
|
|
267
267
|
|
|
268
268
|
# Grab gene traits if they exists
|
|
269
269
|
if self.gene_traits is not None:
|
|
270
|
-
json_obj["GeneTraits"] = self.gene_traits
|
|
270
|
+
json_obj["GeneTraits"] = [str(t) for t in self.gene_traits]
|
|
271
271
|
|
|
272
272
|
# Grab colors if they exists
|
|
273
273
|
color_set_indices = self.get_color_set_indices()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import struct
|
|
2
2
|
from typing import List
|
|
3
|
-
from uuid import UUID
|
|
3
|
+
from uuid import UUID, SafeUUID
|
|
4
4
|
|
|
5
5
|
from ._binary_reader_base import BinaryReaderBase
|
|
6
6
|
from arkparse.logging import ArkSaveLogger
|
|
@@ -24,6 +24,7 @@ def _fast_uuid_from_bytes(b: bytes) -> UUID:
|
|
|
24
24
|
# This is ~3-4x faster than UUID(bytes=b)
|
|
25
25
|
u = object.__new__(UUID)
|
|
26
26
|
object.__setattr__(u, 'int', int.from_bytes(b, 'big'))
|
|
27
|
+
object.__setattr__(u, 'is_safe', SafeUUID.unknown)
|
|
27
28
|
return u
|
|
28
29
|
|
|
29
30
|
class BaseValueParser(BinaryReaderBase):
|
|
@@ -11,6 +11,7 @@ from arkparse.parsing.struct.ark_linear_color import ArkLinearColor
|
|
|
11
11
|
from arkparse.parsing.struct.ark_quat import ArkQuat
|
|
12
12
|
from arkparse.parsing.struct.ark_rotator import ArkRotator
|
|
13
13
|
from arkparse.parsing.struct.ark_vector import ArkVector
|
|
14
|
+
from arkparse.parsing.struct.ark_vector2d import ArkVector2D
|
|
14
15
|
from arkparse.parsing.struct.ark_unique_net_id_repl import ArkUniqueNetIdRepl
|
|
15
16
|
from arkparse.parsing.struct.ark_vector_bool_pair import ArkVectorBoolPair
|
|
16
17
|
from arkparse.parsing.struct.ark_server_custom_folder import ArkServerCustomFolder
|
|
@@ -83,6 +84,7 @@ _STRUCT_READERS: Dict[ArkStructType, Callable[["ArkBinaryParser", int], Any]] =
|
|
|
83
84
|
ArkStructType.Quat: lambda bb, ds: ArkQuat(bb),
|
|
84
85
|
ArkStructType.Rotator: lambda bb, ds: ArkRotator(bb),
|
|
85
86
|
ArkStructType.Vector: lambda bb, ds: ArkVector(bb),
|
|
87
|
+
ArkStructType.Vector2D: lambda bb, ds: ArkVector2D(bb, ds),
|
|
86
88
|
ArkStructType.UniqueNetIdRepl: lambda bb, ds: ArkUniqueNetIdRepl(bb),
|
|
87
89
|
ArkStructType.VectorBoolPair: lambda bb, ds: ArkVectorBoolPair(bb),
|
|
88
90
|
ArkStructType.ArkTrackedActorIdCategoryPairWithBool: lambda bb, ds: ArkTrackedActorIdCategoryPairWithBool(bb),
|
|
@@ -397,6 +399,16 @@ class ArkProperty:
|
|
|
397
399
|
|
|
398
400
|
return prop
|
|
399
401
|
|
|
402
|
+
@staticmethod
|
|
403
|
+
def _has_struct_reader(struct_type: str) -> bool:
|
|
404
|
+
"""Whether this struct type has a dedicated (fixed-layout) reader.
|
|
405
|
+
|
|
406
|
+
Types without one are read generically as a property list; see
|
|
407
|
+
``_read_struct_body`` and the guarded array backup in
|
|
408
|
+
``read_array_property``.
|
|
409
|
+
"""
|
|
410
|
+
return ArkStructType.from_type_name(struct_type) in _STRUCT_READERS
|
|
411
|
+
|
|
400
412
|
@staticmethod
|
|
401
413
|
def read_array_property(key: str, type_: str, position: int, bb: "ArkBinaryParser", data_size: int) -> Tuple["ArkProperty", int]:
|
|
402
414
|
# V14 no position in array
|
|
@@ -428,31 +440,51 @@ class ArkProperty:
|
|
|
428
440
|
bb.set_position(bb.position - 4)
|
|
429
441
|
|
|
430
442
|
array_items = bb.read_uint32()
|
|
443
|
+
array_end = data_start_position + data_size
|
|
431
444
|
|
|
432
|
-
#
|
|
433
|
-
#
|
|
445
|
+
# Structs without a dedicated reader are read generically as a property
|
|
446
|
+
# list (see _read_struct_body). That backup is reliable for well-formed,
|
|
447
|
+
# None-terminated property-list structs but can't be guaranteed for an
|
|
448
|
+
# arbitrary packed layout, so guard it: if a generic element read raises,
|
|
449
|
+
# recover by skipping to the array's known end and record the type for
|
|
450
|
+
# follow-up rather than failing the whole object. A dedicated reader
|
|
451
|
+
# raising is a real bug, so let that propagate.
|
|
452
|
+
has_reader = ArkProperty._has_struct_reader(array_content_type)
|
|
434
453
|
|
|
435
454
|
with log_block(f"Arr({array_content_type})"):
|
|
436
455
|
ArkSaveLogger.parser_log(
|
|
437
456
|
f"[STRUCT ARRAY: key='none'; nr_of_value={array_items}; type={array_content_type}; bin_length={data_size}]"
|
|
438
457
|
)
|
|
439
|
-
struct_array = [
|
|
440
|
-
|
|
441
|
-
for _ in range(array_items)
|
|
442
|
-
|
|
458
|
+
struct_array = []
|
|
459
|
+
try:
|
|
460
|
+
for _ in range(array_items):
|
|
461
|
+
struct_array.append(
|
|
462
|
+
ArkProperty.read_struct_property(bb, data_size, array_content_type, True)[0]
|
|
463
|
+
)
|
|
464
|
+
except Exception as exc:
|
|
465
|
+
if has_reader:
|
|
466
|
+
raise
|
|
467
|
+
ArkSaveLogger.warning_log(
|
|
468
|
+
f"Generic read of struct array '{array_content_type}' failed after "
|
|
469
|
+
f"{len(struct_array)}/{array_items} element(s): {exc}; skipping to end of array"
|
|
470
|
+
)
|
|
471
|
+
ArkSaveLogger._notify_struct_mismatch(
|
|
472
|
+
array_content_type, data_size, data_start_position, bb.position, bb
|
|
473
|
+
)
|
|
474
|
+
bb.set_position(array_end)
|
|
443
475
|
|
|
444
476
|
prop = ArkProperty(key, type_, position, 0, struct_array)
|
|
445
|
-
if bb.position !=
|
|
477
|
+
if bb.position != array_end:
|
|
478
|
+
# The read didn't consume exactly the declared size. Record the
|
|
479
|
+
# mismatch (the testbench captures these) and realign to the end.
|
|
446
480
|
ArkSaveLogger.warning_log(
|
|
447
|
-
f"Array
|
|
481
|
+
f"Array of struct '{array_content_type}' read incorrectly, "
|
|
482
|
+
f"bytes off: {array_end - bb.position}; realigning to end of array"
|
|
448
483
|
)
|
|
449
|
-
ArkSaveLogger.
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
# if array_content_type == "PrimalCharacterStatusValueModifier":
|
|
455
|
-
# ArkSaveLogger.set_log_level(ArkSaveLogger.LogTypes.PARSER, False)
|
|
484
|
+
ArkSaveLogger._notify_struct_mismatch(
|
|
485
|
+
array_content_type, data_size, data_start_position, bb.position, bb
|
|
486
|
+
)
|
|
487
|
+
bb.set_position(array_end)
|
|
456
488
|
|
|
457
489
|
return prop, start_values_pos
|
|
458
490
|
|
|
@@ -549,17 +581,19 @@ class ArkProperty:
|
|
|
549
581
|
ArkSaveLogger.parser_log(f"Reading struct {struct_type} with data size {data_size}")
|
|
550
582
|
return _STRUCT_READERS[ark_struct_type](bb, data_size)
|
|
551
583
|
if in_array:
|
|
584
|
+
# No dedicated reader for this struct type. Fall through to the
|
|
585
|
+
# generic property-list read below — the designed backup for unknown
|
|
586
|
+
# structs in arrays. It reads cleanly for well-formed, None-terminated
|
|
587
|
+
# property-list structs, and read_array_property validates the array's
|
|
588
|
+
# total size and recovers from any type it can't fully consume, so
|
|
589
|
+
# this is not by itself an error. Record the type once (quietly) so it
|
|
590
|
+
# is discoverable without the noise of a per-type warning.
|
|
552
591
|
if struct_type not in UNSUPPORTED_STRUCTS:
|
|
553
|
-
ArkSaveLogger.
|
|
592
|
+
ArkSaveLogger.parser_log(
|
|
593
|
+
f"No dedicated reader for struct '{struct_type}' in array; "
|
|
594
|
+
f"reading generically as a property list"
|
|
595
|
+
)
|
|
554
596
|
UNSUPPORTED_STRUCTS.append(struct_type)
|
|
555
|
-
|
|
556
|
-
# uncomment the lines below if you want to make objects of unknown structs
|
|
557
|
-
# ArkSaveLogger.parser_log(f"Reading struct {struct_type} as array")
|
|
558
|
-
# bb.structured_print(to_default_file=True)
|
|
559
|
-
# bb.store()
|
|
560
|
-
# ArkSaveLogger.error_log(f"Unsupported struct type {struct_type} in array")
|
|
561
|
-
# ArkSaveLogger.open_hex_view(True)
|
|
562
|
-
# raise ValueError(f"Unsupported struct type {struct_type}")
|
|
563
597
|
|
|
564
598
|
ArkSaveLogger.parser_log(f"Reading struct {struct_type} with data size {data_size} as property list at position {bb.get_position()}")
|
|
565
599
|
# Fallback: struct as property list
|
|
@@ -11,6 +11,7 @@ from .ark_tracked_actor_id_category_pair import ArkTrackedActorIdCategoryPair
|
|
|
11
11
|
from .ark_unique_net_id_repl import ArkUniqueNetIdRepl
|
|
12
12
|
from .ark_vector_bool_pair import ArkVectorBoolPair
|
|
13
13
|
from .ark_vector import ArkVector
|
|
14
|
+
from .ark_vector2d import ArkVector2D
|
|
14
15
|
from .object_reference import ObjectReference, get_uuid_reference_bytes
|
|
15
16
|
from .unknown_struct import UnknownStruct
|
|
16
17
|
from .ark_custom_item_data import ArkCustomItemData
|