rpfm_lib/files/group_formations/versions/
shogun_2.rs1use crate::binary::{ReadBytes, WriteBytes};
12use crate::error::Result;
13
14use super::*;
15use super::versions::v1;
16
17impl GroupFormations {
18
19 pub(crate) fn decode_sho_2<R: ReadBytes>(&mut self, data: &mut R) -> Result<()> {
20
21 for _ in 0..data.read_u32()? {
23 let mut formation = GroupFormation::default();
24 formation.name = data.read_sized_string_u16()?;
25 formation.ai_priority = data.read_f32()?;
26 formation.ai_purpose = AIPurpose::V1(v1::AIPurposeFlags::from_bits_truncate(data.read_u32()?));
27
28 for _ in 0..data.read_u32()? {
30 let mut min_unit_category_percentage = MinUnitCategoryPercentage::default();
31 min_unit_category_percentage.category = UnitCategory::try_from(data.read_u32()?)?;
32 min_unit_category_percentage.percentage = data.read_u32()?;
33 formation.min_unit_category_percentage.push(min_unit_category_percentage);
34 }
35
36 for _ in 0..data.read_u32()? {
38 formation.ai_supported_factions.push(data.read_sized_string_u16()?);
39 }
40
41 for _ in 0..data.read_u32()? {
43 let mut block = GroupFormationBlock::default();
44 block.block_id = data.read_u32()?;
45
46 let block_type = data.read_u32()?;
47 match block_type {
48
49 0 => {
51 let mut container = ContainerAbsolute::default();
52 container.block_priority = data.read_f32()?;
53 container.entity_arrangement = EntityArrangement::try_from(data.read_u32()?)?;
54 container.inter_entity_spacing = data.read_f32()?;
55 container.crescent_y_offset = data.read_f32()?;
56 container.position_x = data.read_f32()?;
57 container.position_y = data.read_f32()?;
58 container.minimum_entity_threshold = data.read_i32()?;
59 container.maximum_entity_threshold = data.read_i32()?;
60
61 for _ in 0..data.read_u32()? {
62 let mut entity_pref = EntityPreference::default();
63 entity_pref.priority = data.read_f32()?;
64 entity_pref.entity = Entity::V1(v1::EntityType::try_from(data.read_u32()?)?);
65 container.entity_preferences.push(entity_pref);
66 }
67
68 block.block = Block::ContainerAbsolute(container);
69 },
70
71 1 => {
73 let mut container = ContainerRelative::default();
74 container.block_priority = data.read_f32()?;
75 container.relative_block_id = data.read_u32()?;
76 container.entity_arrangement = EntityArrangement::try_from(data.read_u32()?)?;
77 container.inter_entity_spacing = data.read_f32()?;
78 container.crescent_y_offset = data.read_f32()?;
79 container.position_x = data.read_f32()?;
80 container.position_y = data.read_f32()?;
81 container.minimum_entity_threshold = data.read_i32()?;
82 container.maximum_entity_threshold = data.read_i32()?;
83
84 for _ in 0..data.read_u32()? {
85 let mut entity_pref = EntityPreference::default();
86 entity_pref.priority = data.read_f32()?;
87 entity_pref.entity = Entity::V1(v1::EntityType::try_from(data.read_u32()?)?);
88 container.entity_preferences.push(entity_pref);
89 }
90
91 block.block = Block::ContainerRelative(container);
92 },
93
94 3 => {
96 let mut container = Spanning::default();
97 for _ in 0..data.read_u32()? {
98 container.spanned_block_ids.push(data.read_u32()?);
99 }
100 block.block = Block::Spanning(container);
101 },
102 _ => todo!("unknown block type {}.", block_type),
103 }
104
105 formation.group_formation_blocks.push(block);
106 }
107
108 self.formations.push(formation);
109 }
110
111 Ok(())
112 }
113
114 pub(crate) fn encode_sho_2<W: WriteBytes>(&mut self, buffer: &mut W) -> Result<()> {
115 buffer.write_u32(self.formations.len() as u32)?;
116 for formation in self.formations() {
117 buffer.write_sized_string_u16(formation.name())?;
118 buffer.write_f32(formation.ai_priority)?;
119
120 if let AIPurpose::V1(data) = &formation.ai_purpose {
121 buffer.write_u32(data.bits())?;
122 }
123
124 buffer.write_u32(formation.min_unit_category_percentage.len() as u32)?;
125 for mucp in formation.min_unit_category_percentage() {
126 buffer.write_u32(mucp.category.into())?;
127 buffer.write_u32(mucp.percentage)?;
128 }
129
130 buffer.write_u32(formation.ai_supported_factions.len() as u32)?;
131 for s in formation.ai_supported_factions() {
132 buffer.write_sized_string_u16(s)?;
133 }
134
135 buffer.write_u32(formation.group_formation_blocks.len() as u32)?;
136 for block in formation.group_formation_blocks() {
137 buffer.write_u32(block.block_id)?;
138
139 match block.block {
140 Block::ContainerAbsolute(ref b) => {
141 buffer.write_u32(0)?;
142 buffer.write_f32(b.block_priority)?;
143 buffer.write_u32(b.entity_arrangement.into())?;
144 buffer.write_f32(b.inter_entity_spacing)?;
145 buffer.write_f32(b.crescent_y_offset)?;
146 buffer.write_f32(b.position_x)?;
147 buffer.write_f32(b.position_y)?;
148 buffer.write_i32(b.minimum_entity_threshold)?;
149 buffer.write_i32(b.maximum_entity_threshold)?;
150
151 buffer.write_u32(b.entity_preferences.len() as u32)?;
152 for ep in b.entity_preferences() {
153 buffer.write_f32(ep.priority)?;
154 if let Entity::V1(data) = &ep.entity {
155 buffer.write_u32((*data).into())?;
156 }
157 }
158 },
159
160 Block::ContainerRelative(ref b) => {
161 buffer.write_u32(1)?;
162 buffer.write_f32(b.block_priority)?;
163 buffer.write_u32(b.relative_block_id)?;
164 buffer.write_u32(b.entity_arrangement.into())?;
165 buffer.write_f32(b.inter_entity_spacing)?;
166 buffer.write_f32(b.crescent_y_offset)?;
167 buffer.write_f32(b.position_x)?;
168 buffer.write_f32(b.position_y)?;
169 buffer.write_i32(b.minimum_entity_threshold)?;
170 buffer.write_i32(b.maximum_entity_threshold)?;
171
172 buffer.write_u32(b.entity_preferences.len() as u32)?;
173 for ep in b.entity_preferences() {
174 buffer.write_f32(ep.priority)?;
175 if let Entity::V1(data) = &ep.entity {
176 buffer.write_u32((*data).into())?;
177 }
178 }
179 },
180
181 Block::Spanning(ref b) => {
182 buffer.write_u32(3)?;
183 buffer.write_u32(b.spanned_block_ids.len() as u32)?;
184 for id in b.spanned_block_ids() {
185 buffer.write_u32(*id)?;
186 }
187 },
188 }
189 }
190 }
191
192 Ok(())
193 }
194}