fivefury 0.2.7__tar.gz → 0.2.9__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.
- {fivefury-0.2.7 → fivefury-0.2.9}/PKG-INFO +43 -1
- fivefury-0.2.7/fivefury.egg-info/PKG-INFO → fivefury-0.2.9/README.md +41 -12
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/__init__.py +58 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/bounds/model.py +5 -5
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cache/core.py +42 -3
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cache/io.py +6 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cache/scan.py +1 -1
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cdr/model.py +1 -1
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/gamefile.py +6 -1
- fivefury-0.2.9/fivefury/heightmap/__init__.py +31 -0
- fivefury-0.2.9/fivefury/heightmap/io.py +373 -0
- fivefury-0.2.9/fivefury/heightmap/model.py +535 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/rel/model.py +4 -4
- fivefury-0.2.9/fivefury/water/__init__.py +30 -0
- fivefury-0.2.9/fivefury/water/geometry.py +99 -0
- fivefury-0.2.9/fivefury/water/io.py +195 -0
- fivefury-0.2.9/fivefury/water/model.py +573 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/builder.py +2 -1
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/model.py +1 -1
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/prepare.py +91 -2
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/writer.py +2 -1
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/entities.py +2 -2
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymt/__init__.py +1 -1
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytyp/mlo.py +2 -2
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytyp/timed_archetype.py +2 -2
- fivefury-0.2.7/README.md → fivefury-0.2.9/fivefury.egg-info/PKG-INFO +54 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury.egg-info/SOURCES.txt +10 -1
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury.egg-info/requires.txt +1 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/py_bindings.h +4 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/py_crypto.cpp +14 -10
- {fivefury-0.2.7 → fivefury-0.2.9}/native/py_index.cpp +14 -8
- {fivefury-0.2.7 → fivefury-0.2.9}/native/rpf_archive.cpp +7 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/pyproject.toml +5 -2
- {fivefury-0.2.7 → fivefury-0.2.9}/setup.py +4 -1
- fivefury-0.2.9/tests/test_heightmap.py +160 -0
- fivefury-0.2.9/tests/test_python_compat.py +57 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_rpf_streaming_folder.py +63 -1
- fivefury-0.2.9/tests/test_water.py +317 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_ybn.py +4 -3
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_ydr.py +9 -13
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_ydr_builder.py +24 -0
- fivefury-0.2.7/tests/test_ymap_occluders.py +0 -37
- {fivefury-0.2.7 → fivefury-0.2.9}/LICENSE +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/MANIFEST.in +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/_native.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/assets/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/assets/base.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/assets/ydd.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/assets/ydr.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/assets/yft.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/assets/ypt.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/awc/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/awc/audio.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/awc/constants.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/awc/conversion.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/awc/crypto.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/awc/io.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/awc/structures.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/binary.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/bounds/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/bounds/geometry.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/bounds/materials.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/bounds/reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/bounds/writer.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/buckets.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cache/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cache/assets.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cache/kinds.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cache/paths.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cache/views.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cdr/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cdr/reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cdr/resource.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cdr/shaders.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cdr/vertices.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/colors.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/common.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/crypto/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/crypto/backends.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/crypto/keys.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/analysis.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/dsl.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/events.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/flags.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/lights.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/model.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/names.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/payloads.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/pso.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/scene/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/scene/base.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/scene/bindings.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/scene/core.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/scene/event_api.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/scene/io.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/scene/shared.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/scene/subtitles.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/scene/timeline.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/scene/validation.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/schema.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/write.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/cut/xml.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/data/lut.dat +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/data/magic.dat +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/data/ng.dat +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/dlc/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/dlc/enums.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/dlc/highlevel.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/dlc/model.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/dlc/xml.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/drawable/Shaders.xml +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/drawable/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/drawable/lod.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/drawable/model.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/drawable/shaders.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/game_target.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/gtxd.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/gxt2.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/hashing.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/meta/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/meta/backed.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/meta/builder.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/meta/defs.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/meta/read.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/meta/resource.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/meta/utils.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/metahash.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/pso/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/pso/codec.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/pso/model.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/pso/reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/pso/schema.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/pso/writer.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/rbf.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/rel/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/rel/enums.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/rel/io.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/resolver.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/resource.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/resource_textures.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/rpf/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/rpf/convert.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/rpf/entries.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/rpf/modes.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/rpf/ps3.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/rpf/streaming.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/rpf/utils.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/texture.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/vector.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/vehiclemeta/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/vehiclemeta/carcols.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/vehiclemeta/common.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/vehiclemeta/enums.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/vehiclemeta/handling.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/vehiclemeta/resource.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/vehiclemeta/variations.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/vehiclemeta/vehicles.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/xml.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ybn/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ybn/mlo.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ycd/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ycd/cutscene.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ycd/model.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ycd/reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ycd/sequence_channels.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ycd/sequence_codec.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ycd/sequence_tracks.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ycd/sequences.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ycd/write.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydd/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydd/model.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydd/reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydd/rigging.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydd/writer.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/ShadersGen9Conversion.xml +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/assimp.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/build_types.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/collision.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/defs.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/gen9.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/gen9_shader_enums.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/gen9_shader_info.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/materials.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/read_joints.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/read_lights.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/read_materials.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/read_skeleton.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/rigging.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/shader_enums.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/shader_info.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/shaders.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/write_buffers.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/write_drawable.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/write_geometry.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/write_joints.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/write_lights.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/write_materials.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/write_models.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ydr/write_skeleton.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yed/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yed/audit.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yed/constants.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yed/enums.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yed/instructions.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yed/model.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yed/ped.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yed/reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yed/writer.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/cloth.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/cloth_reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/cloth_writer.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/constants.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/corpus.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/drawable_reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/drawables.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/events.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/events_reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/events_writer.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/fields_reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/fragment.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/fragment_drawable.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/glass.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/glass_reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/glass_writer.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/io_helpers.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/matrices.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/matrices_reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/matrices_writer.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/model.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/physics.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/physics_authoring.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/physics_reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/physics_writer.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/pointers.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/stats.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/yft/validation.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/base.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/blocks.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/cargens.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/defs.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/enums.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/extension_defs.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/extensions.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/grass.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/io.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/lights.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/mlo_validation.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/model.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/occluders.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/packing.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/surfaces.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/timecycle.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymap/utils.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymf/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymf/builder.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymf/enums.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymf/model.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymf/pso.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymf/resource.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymf/schema.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymf/utils.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymt/ped_metadata.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymt/ped_variation.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymt/scenario.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ymt/streaming.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ynd/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ynd/heightmaps.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ynd/model.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ynd/network.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ynd/reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ynd/regions.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ynd/writer.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ynv/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ynv/assimp.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ynv/model.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ynv/reader.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ynv/writer.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytd/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytd/defs.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytd/model.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytyp/__init__.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytyp/archetypes.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytyp/asset_types.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytyp/base_archetype.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytyp/defs.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytyp/extension_defs.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytyp/extensions.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytyp/flags.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytyp/helpers.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytyp/lod.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytyp/mlo_validation.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury/ytyp/model.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury.egg-info/dependency_links.txt +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/fivefury.egg-info/top_level.txt +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/bounds_algorithms.cpp +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/bounds_algorithms.h +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/bounds_python.cpp +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/bounds_python.h +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/bounds_types.h +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/crypto_magic.cpp +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/crypto_magic.h +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/py_bindings.cpp +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/py_bounds.cpp +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/py_module.cpp +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/py_resource.cpp +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/py_rpf.cpp +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/py_vertex.cpp +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/resource_layout.cpp +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/resource_layout.h +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/rpf_archive.h +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/rpf_crypto.cpp +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/rpf_index.cpp +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/rpf_index.h +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/rpf_read.cpp +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/rpf_scan.cpp +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/native/rpf_scan.h +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/setup.cfg +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_cdr.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_cut.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_cut_dsl.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_cut_no_template.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_dlc.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_drawable.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_gtxd.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_hashing.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_meta_rpf_contracts.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_mlo.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_rpf_ps3.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_vehiclemeta.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_ycd.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_ycd_cutscene_builder.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_ydd.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_ydr_shaders.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_yft.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_ymf.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_ynd.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_ynv.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_ynv_assimp.py +0 -0
- {fivefury-0.2.7 → fivefury-0.2.9}/tests/test_ytyp_flags.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fivefury
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: Python library for GTA V asset workflows including YMAP, YTYP, RPF, YTD and GameFileCache utilities.
|
|
5
5
|
Author: Codex
|
|
6
6
|
License-Expression: CC0-1.0
|
|
@@ -8,6 +8,7 @@ Requires-Python: >=3.11
|
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
9
|
License-File: LICENSE
|
|
10
10
|
Requires-Dist: miniaudio>=1.71
|
|
11
|
+
Requires-Dist: numpy>=1.26
|
|
11
12
|
Dynamic: license-file
|
|
12
13
|
|
|
13
14
|
# FiveFury
|
|
@@ -41,6 +42,8 @@ The Assimp-backed import helpers (`assimp_to_ydr`, `obj_to_ydr`, `fbx_to_ydr`, `
|
|
|
41
42
|
| `YTD` | Full | Texture dictionaries: read/write, extraction, embedded-asset helpers |
|
|
42
43
|
| `YND` | Full | Path nodes, links, area partitioning, junction heightmaps |
|
|
43
44
|
| `YNV` | Full | Navmeshes: sectors, polys, portals, validation, basic OBJ partitioning |
|
|
45
|
+
| `heightmap.dat` | Full | World-height grids, native quantization, row RLE, water masks, spatial queries |
|
|
46
|
+
| `water.xml` | Full | Water surfaces, triangle corners, calming regions, wave amplitude and direction |
|
|
44
47
|
| `CUT` | Full | Cutscenes, plus the readable `.cuts` script format for round-trip authoring |
|
|
45
48
|
| `GXT2` | Full | Hashed text tables with binary read/write and text import/export |
|
|
46
49
|
| `AWC` | Full | Audio containers: PCM/WAV extraction, authoring from WAV/MP3/OGG/FLAC |
|
|
@@ -114,6 +117,45 @@ save_ybn(bound, "floor_collision.ybn")
|
|
|
114
117
|
|
|
115
118
|
Generated geometry is chunked as needed and gets BVH and octant data. The same bounds model backs standalone `YBN` files, embedded `YDR` collisions, and `YFT` physics — a drawable's render mesh can also be converted directly with `ydr.ensure_bound_from_render_geometry()`.
|
|
116
119
|
|
|
120
|
+
### Author water
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from fivefury import WaterData, WaterQuad, WaterWaveQuad
|
|
124
|
+
|
|
125
|
+
water = WaterData()
|
|
126
|
+
water.add(
|
|
127
|
+
WaterQuad.rectangle(
|
|
128
|
+
center=(100.0, 200.0, 12.5),
|
|
129
|
+
size=(80.0, 40.0),
|
|
130
|
+
alpha=26,
|
|
131
|
+
limited_depth=True,
|
|
132
|
+
)
|
|
133
|
+
)
|
|
134
|
+
water.add(
|
|
135
|
+
WaterWaveQuad.from_angle(
|
|
136
|
+
bounds=(60, 180, 140, 220),
|
|
137
|
+
amplitude=1.2,
|
|
138
|
+
degrees=90.0,
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
water.translate(x=500, y=-200, z=20.0).save("water.xml")
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Author a world height map
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from fivefury import HeightMap, HeightMapBounds
|
|
148
|
+
|
|
149
|
+
heightmap = HeightMap.empty(
|
|
150
|
+
columns=10,
|
|
151
|
+
rows=10,
|
|
152
|
+
bounds=HeightMapBounds(0.0, 0.0, 0.0, 500.0, 500.0, 800.0),
|
|
153
|
+
)
|
|
154
|
+
heightmap.set_height(4, 6, minimum=32.0, maximum=78.0)
|
|
155
|
+
heightmap.set_water(4, 6)
|
|
156
|
+
heightmap.save("heightmap.dat")
|
|
157
|
+
```
|
|
158
|
+
|
|
117
159
|
### Convert audio to AWC
|
|
118
160
|
|
|
119
161
|
```python
|
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: fivefury
|
|
3
|
-
Version: 0.2.7
|
|
4
|
-
Summary: Python library for GTA V asset workflows including YMAP, YTYP, RPF, YTD and GameFileCache utilities.
|
|
5
|
-
Author: Codex
|
|
6
|
-
License-Expression: CC0-1.0
|
|
7
|
-
Requires-Python: >=3.11
|
|
8
|
-
Description-Content-Type: text/markdown
|
|
9
|
-
License-File: LICENSE
|
|
10
|
-
Requires-Dist: miniaudio>=1.71
|
|
11
|
-
Dynamic: license-file
|
|
12
|
-
|
|
13
1
|
# FiveFury
|
|
14
2
|
|
|
15
3
|
FiveFury is a Python library for reading, writing, and packaging GTA V asset files: drawables, collisions, map metadata, animations, navigation data, texture dictionaries, text tables, audio containers, cutscenes, DLC metadata, and RPF archives.
|
|
@@ -41,6 +29,8 @@ The Assimp-backed import helpers (`assimp_to_ydr`, `obj_to_ydr`, `fbx_to_ydr`, `
|
|
|
41
29
|
| `YTD` | Full | Texture dictionaries: read/write, extraction, embedded-asset helpers |
|
|
42
30
|
| `YND` | Full | Path nodes, links, area partitioning, junction heightmaps |
|
|
43
31
|
| `YNV` | Full | Navmeshes: sectors, polys, portals, validation, basic OBJ partitioning |
|
|
32
|
+
| `heightmap.dat` | Full | World-height grids, native quantization, row RLE, water masks, spatial queries |
|
|
33
|
+
| `water.xml` | Full | Water surfaces, triangle corners, calming regions, wave amplitude and direction |
|
|
44
34
|
| `CUT` | Full | Cutscenes, plus the readable `.cuts` script format for round-trip authoring |
|
|
45
35
|
| `GXT2` | Full | Hashed text tables with binary read/write and text import/export |
|
|
46
36
|
| `AWC` | Full | Audio containers: PCM/WAV extraction, authoring from WAV/MP3/OGG/FLAC |
|
|
@@ -114,6 +104,45 @@ save_ybn(bound, "floor_collision.ybn")
|
|
|
114
104
|
|
|
115
105
|
Generated geometry is chunked as needed and gets BVH and octant data. The same bounds model backs standalone `YBN` files, embedded `YDR` collisions, and `YFT` physics — a drawable's render mesh can also be converted directly with `ydr.ensure_bound_from_render_geometry()`.
|
|
116
106
|
|
|
107
|
+
### Author water
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
from fivefury import WaterData, WaterQuad, WaterWaveQuad
|
|
111
|
+
|
|
112
|
+
water = WaterData()
|
|
113
|
+
water.add(
|
|
114
|
+
WaterQuad.rectangle(
|
|
115
|
+
center=(100.0, 200.0, 12.5),
|
|
116
|
+
size=(80.0, 40.0),
|
|
117
|
+
alpha=26,
|
|
118
|
+
limited_depth=True,
|
|
119
|
+
)
|
|
120
|
+
)
|
|
121
|
+
water.add(
|
|
122
|
+
WaterWaveQuad.from_angle(
|
|
123
|
+
bounds=(60, 180, 140, 220),
|
|
124
|
+
amplitude=1.2,
|
|
125
|
+
degrees=90.0,
|
|
126
|
+
)
|
|
127
|
+
)
|
|
128
|
+
water.translate(x=500, y=-200, z=20.0).save("water.xml")
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Author a world height map
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from fivefury import HeightMap, HeightMapBounds
|
|
135
|
+
|
|
136
|
+
heightmap = HeightMap.empty(
|
|
137
|
+
columns=10,
|
|
138
|
+
rows=10,
|
|
139
|
+
bounds=HeightMapBounds(0.0, 0.0, 0.0, 500.0, 500.0, 800.0),
|
|
140
|
+
)
|
|
141
|
+
heightmap.set_height(4, 6, minimum=32.0, maximum=78.0)
|
|
142
|
+
heightmap.set_water(4, 6)
|
|
143
|
+
heightmap.save("heightmap.dat")
|
|
144
|
+
```
|
|
145
|
+
|
|
117
146
|
### Convert audio to AWC
|
|
118
147
|
|
|
119
148
|
```python
|
|
@@ -459,6 +459,37 @@ from .rpf import (
|
|
|
459
459
|
zip_to_rpf,
|
|
460
460
|
)
|
|
461
461
|
from .texture import BCFormat
|
|
462
|
+
from .heightmap import (
|
|
463
|
+
HeightCell,
|
|
464
|
+
HeightGrid,
|
|
465
|
+
HeightMap,
|
|
466
|
+
HeightMapBounds,
|
|
467
|
+
HeightMapByteOrder,
|
|
468
|
+
HeightMapCellFormat,
|
|
469
|
+
HeightMapFlags,
|
|
470
|
+
HeightMapValidationError,
|
|
471
|
+
build_heightmap_bytes,
|
|
472
|
+
create_heightmap,
|
|
473
|
+
read_heightmap,
|
|
474
|
+
save_heightmap,
|
|
475
|
+
)
|
|
476
|
+
from .water import (
|
|
477
|
+
WaterAlpha,
|
|
478
|
+
WaterBounds,
|
|
479
|
+
WaterCalmingQuad,
|
|
480
|
+
WaterComponent,
|
|
481
|
+
WaterCornerAlphas,
|
|
482
|
+
WaterData,
|
|
483
|
+
WaterQuad,
|
|
484
|
+
WaterQuadType,
|
|
485
|
+
WaterValidationError,
|
|
486
|
+
WaterWaveQuad,
|
|
487
|
+
build_water_xml,
|
|
488
|
+
coerce_water_data,
|
|
489
|
+
create_water,
|
|
490
|
+
read_water,
|
|
491
|
+
save_water,
|
|
492
|
+
)
|
|
462
493
|
from .ydr import (
|
|
463
494
|
AssimpMaterial,
|
|
464
495
|
AssimpScene,
|
|
@@ -1201,6 +1232,14 @@ __all__ = [
|
|
|
1201
1232
|
"GameTarget",
|
|
1202
1233
|
"GameCrypto",
|
|
1203
1234
|
"GameFileType",
|
|
1235
|
+
"HeightCell",
|
|
1236
|
+
"HeightGrid",
|
|
1237
|
+
"HeightMap",
|
|
1238
|
+
"HeightMapBounds",
|
|
1239
|
+
"HeightMapByteOrder",
|
|
1240
|
+
"HeightMapCellFormat",
|
|
1241
|
+
"HeightMapFlags",
|
|
1242
|
+
"HeightMapValidationError",
|
|
1204
1243
|
"GXT2_MAGIC",
|
|
1205
1244
|
"GXT2_MAGIC_BYTES",
|
|
1206
1245
|
"Gxt2",
|
|
@@ -1310,6 +1349,16 @@ __all__ = [
|
|
|
1310
1349
|
"VehicleVariation",
|
|
1311
1350
|
"VehicleWheelType",
|
|
1312
1351
|
"VehicleWindow",
|
|
1352
|
+
"WaterAlpha",
|
|
1353
|
+
"WaterBounds",
|
|
1354
|
+
"WaterCalmingQuad",
|
|
1355
|
+
"WaterComponent",
|
|
1356
|
+
"WaterCornerAlphas",
|
|
1357
|
+
"WaterData",
|
|
1358
|
+
"WaterQuad",
|
|
1359
|
+
"WaterQuadType",
|
|
1360
|
+
"WaterValidationError",
|
|
1361
|
+
"WaterWaveQuad",
|
|
1313
1362
|
"WalkDontWalkExtension",
|
|
1314
1363
|
"WindDisturbanceExtension",
|
|
1315
1364
|
"Ycd",
|
|
@@ -1567,7 +1616,9 @@ __all__ = [
|
|
|
1567
1616
|
"infer_archetype_radius",
|
|
1568
1617
|
"mark_cutscene_prop_archetypes",
|
|
1569
1618
|
"assimp_to_ydr",
|
|
1619
|
+
"build_heightmap_bytes",
|
|
1570
1620
|
"build_rsc7",
|
|
1621
|
+
"build_water_xml",
|
|
1571
1622
|
"build_ynv_bytes",
|
|
1572
1623
|
"build_ynv_system_layout",
|
|
1573
1624
|
"build_bound_from_render_geometry",
|
|
@@ -1589,11 +1640,14 @@ __all__ = [
|
|
|
1589
1640
|
"clear_hash_resolver",
|
|
1590
1641
|
"clear_game_crypto",
|
|
1591
1642
|
"create_rpf",
|
|
1643
|
+
"create_heightmap",
|
|
1644
|
+
"create_water",
|
|
1592
1645
|
"create_ymf_for_ymaps",
|
|
1593
1646
|
"create_ydd",
|
|
1594
1647
|
"create_ydr",
|
|
1595
1648
|
"convert_audio_to_awc",
|
|
1596
1649
|
"coerce_ped_component",
|
|
1650
|
+
"coerce_water_data",
|
|
1597
1651
|
"ensure_game_crypto",
|
|
1598
1652
|
"get_game_crypto",
|
|
1599
1653
|
"get_hash_resolver",
|
|
@@ -1670,6 +1724,8 @@ __all__ = [
|
|
|
1670
1724
|
"read_ynv",
|
|
1671
1725
|
"read_ymap",
|
|
1672
1726
|
"read_vehicle_meta",
|
|
1727
|
+
"read_water",
|
|
1728
|
+
"read_heightmap",
|
|
1673
1729
|
"read_ymf",
|
|
1674
1730
|
"read_ymf_xml",
|
|
1675
1731
|
"read_ymt",
|
|
@@ -1699,6 +1755,8 @@ __all__ = [
|
|
|
1699
1755
|
"save_ymt",
|
|
1700
1756
|
"save_ytd",
|
|
1701
1757
|
"save_ytyp",
|
|
1758
|
+
"save_water",
|
|
1759
|
+
"save_heightmap",
|
|
1702
1760
|
"set_ped_drawable_cloth",
|
|
1703
1761
|
"time_flags",
|
|
1704
1762
|
"save_cut",
|
|
@@ -1054,7 +1054,7 @@ class BoundGeometry(Bound):
|
|
|
1054
1054
|
return material
|
|
1055
1055
|
|
|
1056
1056
|
def build(self) -> "BoundGeometry":
|
|
1057
|
-
|
|
1057
|
+
Bound.build(self)
|
|
1058
1058
|
for index, polygon in enumerate(self.polygons):
|
|
1059
1059
|
polygon.index = index
|
|
1060
1060
|
if isinstance(polygon, BoundPolygonTriangle):
|
|
@@ -1079,7 +1079,7 @@ class BoundGeometry(Bound):
|
|
|
1079
1079
|
return self
|
|
1080
1080
|
|
|
1081
1081
|
def validate(self) -> list[str]:
|
|
1082
|
-
issues =
|
|
1082
|
+
issues = Bound.validate(self)
|
|
1083
1083
|
if len(self.polygon_material_indices) != len(self.polygons):
|
|
1084
1084
|
issues.append("polygon_material_indices length does not match polygon count")
|
|
1085
1085
|
for polygon_index, polygon in enumerate(self.polygons):
|
|
@@ -1164,7 +1164,7 @@ class BoundComposite(Bound):
|
|
|
1164
1164
|
def compute_volume(self) -> float:
|
|
1165
1165
|
if self.children:
|
|
1166
1166
|
return sum(child.bound.compute_volume() for child in self.children)
|
|
1167
|
-
return
|
|
1167
|
+
return Bound.compute_volume(self)
|
|
1168
1168
|
|
|
1169
1169
|
def compute_center_of_gravity(
|
|
1170
1170
|
self,
|
|
@@ -1226,7 +1226,7 @@ class BoundComposite(Bound):
|
|
|
1226
1226
|
return self.compute_composite_angular_inertia(mass)
|
|
1227
1227
|
|
|
1228
1228
|
def build(self) -> "BoundComposite":
|
|
1229
|
-
|
|
1229
|
+
Bound.build(self)
|
|
1230
1230
|
for child in self.children:
|
|
1231
1231
|
child.bound.build()
|
|
1232
1232
|
if child.bounds is None or not _aabb_is_valid(child.bounds):
|
|
@@ -1252,7 +1252,7 @@ class BoundComposite(Bound):
|
|
|
1252
1252
|
return self
|
|
1253
1253
|
|
|
1254
1254
|
def validate(self) -> list[str]:
|
|
1255
|
-
issues =
|
|
1255
|
+
issues = Bound.validate(self)
|
|
1256
1256
|
if not self.children:
|
|
1257
1257
|
issues.append("Composite bound has no children")
|
|
1258
1258
|
for index, child in enumerate(self.children):
|
|
@@ -4,7 +4,7 @@ from collections import OrderedDict
|
|
|
4
4
|
from collections.abc import Mapping, Sequence
|
|
5
5
|
from dataclasses import dataclass, field
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import Any, Iterator
|
|
7
|
+
from typing import Any, Iterator, Self
|
|
8
8
|
|
|
9
9
|
from .assets import GameFileCacheAssetMixin, TextureRef
|
|
10
10
|
from .io import GameFileCacheIOMixin
|
|
@@ -100,6 +100,12 @@ class GameFileCache(GameFileCacheScanMixin, GameFileCacheAssetMixin, GameFileCac
|
|
|
100
100
|
def __iter__(self) -> Iterator[AssetRecord]:
|
|
101
101
|
return self.iter_assets()
|
|
102
102
|
|
|
103
|
+
def __enter__(self) -> Self:
|
|
104
|
+
return self
|
|
105
|
+
|
|
106
|
+
def __exit__(self, *exc_info: object) -> None:
|
|
107
|
+
self.close()
|
|
108
|
+
|
|
103
109
|
@property
|
|
104
110
|
def scan_complete(self) -> bool:
|
|
105
111
|
return self.last_scan is not None
|
|
@@ -139,7 +145,30 @@ class GameFileCache(GameFileCacheScanMixin, GameFileCacheAssetMixin, GameFileCac
|
|
|
139
145
|
self._texture_parent_view = None
|
|
140
146
|
self._kind_counts_view = None
|
|
141
147
|
|
|
148
|
+
def _close_runtime_archives(self) -> None:
|
|
149
|
+
seen: set[int] = set()
|
|
150
|
+
candidates = [
|
|
151
|
+
*self.archives,
|
|
152
|
+
*self._archive_lookup.values(),
|
|
153
|
+
*self._live_archives.values(),
|
|
154
|
+
]
|
|
155
|
+
for game_file in self.files.values():
|
|
156
|
+
if game_file.archive is not None:
|
|
157
|
+
candidates.append(game_file.archive)
|
|
158
|
+
if isinstance(game_file.parsed, RpfArchive):
|
|
159
|
+
candidates.append(game_file.parsed)
|
|
160
|
+
for archive in candidates:
|
|
161
|
+
identity = id(archive)
|
|
162
|
+
if identity in seen:
|
|
163
|
+
continue
|
|
164
|
+
seen.add(identity)
|
|
165
|
+
archive.close()
|
|
166
|
+
|
|
167
|
+
def close(self) -> None:
|
|
168
|
+
self.clear_runtime_cache(loaded_files=True)
|
|
169
|
+
|
|
142
170
|
def clear(self) -> None:
|
|
171
|
+
self._close_runtime_archives()
|
|
143
172
|
self.archives.clear()
|
|
144
173
|
self.files.clear()
|
|
145
174
|
self.entries.clear()
|
|
@@ -155,6 +184,7 @@ class GameFileCache(GameFileCacheScanMixin, GameFileCacheAssetMixin, GameFileCac
|
|
|
155
184
|
self._invalidate_views()
|
|
156
185
|
|
|
157
186
|
def clear_runtime_cache(self, *, loaded_files: bool = False) -> None:
|
|
187
|
+
self._close_runtime_archives()
|
|
158
188
|
self.archives.clear()
|
|
159
189
|
self.entries.clear()
|
|
160
190
|
self._archive_lookup.clear()
|
|
@@ -300,12 +330,18 @@ class GameFileCache(GameFileCacheScanMixin, GameFileCacheAssetMixin, GameFileCac
|
|
|
300
330
|
normalized = _normalize_key(key)
|
|
301
331
|
limit = max(0, int(self.max_open_archives))
|
|
302
332
|
if limit <= 0:
|
|
333
|
+
for cached in self._archive_lookup.values():
|
|
334
|
+
cached.close()
|
|
303
335
|
self._archive_lookup.clear()
|
|
304
336
|
return
|
|
305
|
-
self._archive_lookup.pop(normalized, None)
|
|
337
|
+
previous = self._archive_lookup.pop(normalized, None)
|
|
338
|
+
if previous is not None and previous is not archive:
|
|
339
|
+
previous.close()
|
|
306
340
|
self._archive_lookup[normalized] = archive
|
|
307
341
|
while len(self._archive_lookup) > limit:
|
|
308
|
-
self._archive_lookup.popitem(last=False)
|
|
342
|
+
_, evicted = self._archive_lookup.popitem(last=False)
|
|
343
|
+
if all(cached is not evicted for cached in self._archive_lookup.values()):
|
|
344
|
+
evicted.close()
|
|
309
345
|
|
|
310
346
|
def _register_asset(
|
|
311
347
|
self,
|
|
@@ -518,6 +554,9 @@ _KIND_DICT_TYPES: dict[str, GameFileType] = {
|
|
|
518
554
|
"GtxdDict": GameFileType.GTXD,
|
|
519
555
|
"AwcDict": GameFileType.AWC,
|
|
520
556
|
"YedDict": GameFileType.YED,
|
|
557
|
+
"HeightMapDict": GameFileType.HEIGHTMAP,
|
|
558
|
+
"WaterDict": GameFileType.WATER,
|
|
559
|
+
"WaterMapDict": GameFileType.WATER,
|
|
521
560
|
}
|
|
522
561
|
|
|
523
562
|
|
|
@@ -10,6 +10,7 @@ from ..cut import read_cut
|
|
|
10
10
|
from ..gamefile import GameFile, GameFileType, guess_game_file_type
|
|
11
11
|
from ..gtxd import read_gtxd
|
|
12
12
|
from ..gxt2 import read_gxt2
|
|
13
|
+
from ..heightmap import read_heightmap
|
|
13
14
|
from ..hashing import _get_lut
|
|
14
15
|
from ..metahash import MetaHash
|
|
15
16
|
from ..rel import read_rel
|
|
@@ -22,6 +23,7 @@ from ..rpf import (
|
|
|
22
23
|
_normalize_key,
|
|
23
24
|
)
|
|
24
25
|
from ..vehiclemeta import read_vehicle_meta
|
|
26
|
+
from ..water import read_water
|
|
25
27
|
from ..ybn import read_ybn
|
|
26
28
|
from ..ycd import read_ycd
|
|
27
29
|
from ..ydd import read_ydd
|
|
@@ -65,6 +67,10 @@ def _decode_dynamic(data: bytes, *, module_name: str, attribute: str, kind: Game
|
|
|
65
67
|
def _decode_payload(path: str, data: bytes, *, raw: bytes | None = None) -> tuple[Any, GameFileType]:
|
|
66
68
|
ext = Path(path).suffix.lower()
|
|
67
69
|
name = Path(path).name.lower()
|
|
70
|
+
if name.startswith("heightmap") and name.endswith(".dat"):
|
|
71
|
+
return _decode_or_fallback(GameFileType.HEIGHTMAP, data, data, read_heightmap)
|
|
72
|
+
if name == "water.xml":
|
|
73
|
+
return _decode_or_fallback(GameFileType.WATER, data, data, read_water)
|
|
68
74
|
if name == "gtxd.meta":
|
|
69
75
|
return _decode_or_fallback(GameFileType.GTXD, data, data, read_gtxd)
|
|
70
76
|
vehicle_meta_type = guess_game_file_type(path)
|
|
@@ -284,7 +284,7 @@ class Cdr(DrawableAsset[CdrMaterial, CdrModel, CdrMesh]):
|
|
|
284
284
|
graphics_data: bytes = dataclasses.field(default=b"", repr=False)
|
|
285
285
|
|
|
286
286
|
def __post_init__(self) -> None:
|
|
287
|
-
|
|
287
|
+
DrawableAsset.__post_init__(self)
|
|
288
288
|
self.render_bucket_masks = {
|
|
289
289
|
DrawableLod(lod): int(mask)
|
|
290
290
|
for lod, mask in self.render_bucket_masks.items()
|
|
@@ -40,6 +40,7 @@ class GameFileType(IntEnum):
|
|
|
40
40
|
YED = 25
|
|
41
41
|
YFD = 27
|
|
42
42
|
HEIGHTMAP = 28
|
|
43
|
+
WATER = 29
|
|
43
44
|
WATERMAP = 29
|
|
44
45
|
MRF = 30
|
|
45
46
|
DISTANT_LIGHTS = 31
|
|
@@ -79,6 +80,9 @@ _FILE_TYPE_MAP: dict[str, GameFileType] = {
|
|
|
79
80
|
|
|
80
81
|
def guess_game_file_type(path: str | Path, default: GameFileType = GameFileType.UNKNOWN) -> GameFileType:
|
|
81
82
|
parsed = Path(str(path))
|
|
83
|
+
normalized_name = parsed.name.lower()
|
|
84
|
+
if normalized_name.startswith("heightmap") and normalized_name.endswith(".dat"):
|
|
85
|
+
return GameFileType.HEIGHTMAP
|
|
82
86
|
named_meta_types = {
|
|
83
87
|
"gtxd.meta": GameFileType.GTXD,
|
|
84
88
|
"vehicles.meta": GameFileType.VEHICLES,
|
|
@@ -88,8 +92,9 @@ def guess_game_file_type(path: str | Path, default: GameFileType = GameFileType.
|
|
|
88
92
|
"carvariations.meta": GameFileType.CAR_VARIATIONS,
|
|
89
93
|
"vehiclelayouts.meta": GameFileType.VEHICLE_LAYOUTS,
|
|
90
94
|
"peds.meta": GameFileType.PEDS,
|
|
95
|
+
"water.xml": GameFileType.WATER,
|
|
91
96
|
}
|
|
92
|
-
named_type = named_meta_types.get(
|
|
97
|
+
named_type = named_meta_types.get(normalized_name)
|
|
93
98
|
if named_type is not None:
|
|
94
99
|
return named_type
|
|
95
100
|
return _FILE_TYPE_MAP.get(parsed.suffix.lower(), default)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from .io import (
|
|
2
|
+
build_heightmap_bytes,
|
|
3
|
+
create_heightmap,
|
|
4
|
+
read_heightmap,
|
|
5
|
+
save_heightmap,
|
|
6
|
+
)
|
|
7
|
+
from .model import (
|
|
8
|
+
HeightCell,
|
|
9
|
+
HeightGrid,
|
|
10
|
+
HeightMap,
|
|
11
|
+
HeightMapBounds,
|
|
12
|
+
HeightMapByteOrder,
|
|
13
|
+
HeightMapCellFormat,
|
|
14
|
+
HeightMapFlags,
|
|
15
|
+
HeightMapValidationError,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"HeightCell",
|
|
20
|
+
"HeightGrid",
|
|
21
|
+
"HeightMap",
|
|
22
|
+
"HeightMapBounds",
|
|
23
|
+
"HeightMapByteOrder",
|
|
24
|
+
"HeightMapCellFormat",
|
|
25
|
+
"HeightMapFlags",
|
|
26
|
+
"HeightMapValidationError",
|
|
27
|
+
"build_heightmap_bytes",
|
|
28
|
+
"create_heightmap",
|
|
29
|
+
"read_heightmap",
|
|
30
|
+
"save_heightmap",
|
|
31
|
+
]
|